当前位置: 首页 > news >正文

Nacos 中使用了哪些缓存?缓存的目的是什么?是如何实现的?

在这里插入图片描述

Nacos 在服务端和客户端都广泛的使用了缓存机制,下面着重介绍一下。

一、 Nacos 服务端缓存 (Server-Side Caching)

Nacos 服务端缓存的主要目的是提高读取性能、降低对底层存储(数据库或磁盘文件)的压力,并加速对客户端请求的响应

  1. 缓存的内容:

    • 服务实例信息: 注册到 Nacos 的服务实例列表(IP、端口、权重、元数据、健康状态等)。这是服务发现的核心数据,查询频率非常高。
    • 服务信息: 服务的元数据,例如服务名、分组名、保护阈值等。
    • 配置信息: 用户发布的配置内容(按 dataIdgroup 区分)。客户端会频繁拉取或监听配置变更。
    • 集群节点信息: Nacos 集群自身节点的状态和信息。
    • 其他内部状态或元数据: 用于加速内部处理逻辑。
  2. 缓存的目的:

    • 提升读性能/降低延迟: 从内存缓存中读取数据远快于从数据库或磁盘读取,可以极大加速客户端对服务列表或配置内容的查询请求。
    • 减轻存储层负载: 大量的客户端(可能成千上万)会频繁请求服务实例和配置信息。如果每次请求都直接访问数据库,会对数据库造成巨大压力,容易成为性能瓶颈。缓存层可以挡住绝大部分读请求。
    • 提高可用性: 即使底层存储暂时出现抖动,只要缓存中有数据,服务端仍然可以在一定程度上继续提供(可能是稍微过期的)服务发现和配置查询能力。
  3. 实现方式:

    • 内存缓存: 主要使用 JVM 内存作为缓存存储。常见使用 java.util.concurrent.ConcurrentHashMap 等线程安全的 Map 结构来存储缓存数据,Key 通常是服务名、dataId+group 的组合等。
    • 缓存更新机制:
      • 写操作触发更新/失效: 当有数据变更操作时(如服务注册、注销、心跳更新、配置发布/删除),Nacos 首先会更新底层持久化存储(如数据库)。操作成功后,会主动更新或失效相应的内存缓存。这是保证缓存一致性的关键。
      • 事件驱动: Nacos 内部通常有事件发布/订阅机制。当数据发生变化并持久化成功后,会发布一个事件,相关的缓存监听器接收到事件后更新缓存。
      • 一致性协议关联: 在集群模式下,数据的变更通常通过一致性协议(如 Raft 或 Nacos 早期版本的类 Distro 协议)同步到其他节点。当一个节点通过协议成功应用(Apply)了一个数据变更日志后,它会更新自己的内存缓存。这保证了集群中各个节点缓存状态的最终一致性。
      • 懒加载/定时加载 (较少用于核心数据): 某些非核心或不经常变动的数据可能会在首次读取时加载,或通过定时任务定期从存储刷新。但对于服务实例和配置这类核心数据,主动更新是主要方式。
    • 分层缓存 (可能): 某些实现可能会考虑使用多级缓存(如 L1/L2),但 Nacos 的核心缓存主要是基于内存的单层缓存。

二、 Nacos 客户端缓存 (Client-Side Caching)

Nacos 客户端(即你的应用程序中引入 nacos-client 的部分)也实现了缓存,主要目的是提高应用程序性能、降低对 Nacos Server 的请求频率,并在 Nacos Server 短暂不可用时提供一定的容错能力

  1. 缓存的内容:

    • 服务实例列表: 客户端订阅的服务,其可用的实例信息会被缓存在客户端内存中。
    • 配置信息: 客户端获取到的配置内容会被缓存在内存中,并且通常会有一个本地文件快照(Failover 机制)。
  2. 缓存的目的:

    • 提升应用性能: 应用获取服务实例或配置时,可以直接从本地内存缓存读取,避免了网络请求的开销,速度极快。
    • 降低服务端压力: 客户端不需要每次需要数据都去请求 Nacos Server,大大减少了服务端的 QPS。
    • 提高应用容错性/可用性 (Failover):
      • 服务发现: 如果 Nacos Server 暂时宕机或网络不通,客户端仍然可以使用本地缓存的(可能是稍微过期的)服务实例列表进行服务调用,避免完全瘫痪。
      • 配置管理: 如果 Nacos Server 不可用,客户端可以加载本地磁盘上的配置快照文件 (snapshot 目录),保证应用能够使用上一份正确的配置启动或运行。
  3. 实现方式:

    • 内存缓存: 同样主要使用 ConcurrentHashMap 等内存结构存储服务实例和配置。
    • 本地文件快照 (配置管理): Nacos Client 会将成功获取到的配置内容写入到本地磁盘的一个文件中(通常在用户主目录下的 nacos/config 目录的 snapshot 子目录)。当启动时无法连接 Nacos Server 或获取配置失败时,会尝试从这个快照文件加载。
    • 缓存更新机制:
      • 服务发现:
        • 定时拉取: 客户端会定时(可配置)向 Nacos Server 拉取最新的服务实例列表来更新本地缓存。
        • UDP推送 (Nacos 1.x): Nacos 1.x 版本支持服务端通过 UDP 协议主动将变更推送给客户端(但 UDP 不可靠,仍需定时拉取保证)。
        • gRPC 长连接/Watch (Nacos 2.x): Nacos 2.x 推荐使用 gRPC,客户端与服务端建立长连接。当服务实例发生变化时,服务端可以通过长连接主动将变更推送给客户端,实现更实时的更新。即使有推送,通常也会保留定时拉取作为兜底。
      • 配置管理:
        • 长轮询 (Long Polling): 客户端向服务端发起一次获取配置的请求。如果配置没有变更,服务端会 hold 住这个连接一段时间(例如 30 秒)。如果期间配置发生变更,服务端会立即返回变更内容;如果超时仍无变更,服务端返回无变更,客户端收到响应后立即发起下一次长轮询。这种方式可以准实时地获取配置变更,同时避免了大量无效的轮询请求。
        • gRPC 长连接/Watch (Nacos 2.x): 类似服务发现,通过 gRPC 长连接实现配置变更的主动推送。
    • 缓存失效: 客户端缓存通常没有复杂的过期策略,主要依赖于服务端的推送或客户端的定时/长轮询来更新。

总结:

Nacos 中的缓存是其架构设计的核心部分,遍布服务端和客户端。

  • 服务端缓存 主要为了 提升性能和降低存储压力,通过内存缓存和主动更新机制实现。
  • 客户端缓存 主要为了 提升应用性能、降低服务端压力和提供故障容错能力,通过内存缓存、本地文件快照以及与服务端的实时/准实时同步机制(如 gRPC Watch、长轮询)实现。

相关文章:

  • 废物九重境弱者学JS第十天--BOM对象和本地存储
  • UNION和UNION ALL的主要区别
  • UMG:ListView
  • leetcode 188. Best Time to Buy and Sell Stock IV
  • 2N60-ASEMI功业控制与自动化专用2N60
  • MySQL 表varchar字段长度估算
  • 堆栈溢出 StackOverflowError 排查
  • Java反射机制深度解析与应用案例
  • android编译使用共享缓存
  • 常见算法题
  • 【k8s系列1】一主两从结构的环境准备
  • 51单片机实验五:A/D和D/A转换
  • 江湖路远,唯PUT可稳:Express 路由更新招式全解
  • 嵌入式C语言位操作的几种常见用法
  • 视频编解码种类/技术/区别/优缺点汇总
  • 多模态记忆融合:基于LSTM的连续场景生成——突破AI视频生成长度限制
  • 【Qt】初识Qt(二)
  • Oracle 11g通过dg4odbc配置dblink连接PostgreSQL
  • 2021-11-09 C++倍数11各位和为13
  • 25MathorCup选题浅析(睡醒扫一眼题目版)
  • 用了半年的洗衣机竟比马桶还脏,别再这样洗衣服了
  • “30小时不够”,泽连斯基建议延长停火至30天
  • 观察|雀巢咖啡加码中国布局,如何借势云南咖啡打造新增长极?
  • 非法收受财物2.29亿余元,窦万贵受贿案一审开庭
  • 北京:义务教育阶段入学将积极为多孩家庭长幼随学创造条件
  • 2025年青年普法志愿者法治文化基层行活动启动