面试场景题--本地缓存怎么做的?能保证缓存和服务的一致性吗?

在 RPC 调用中,服务地址的获取是高频操作。如果每次调用都直接请求注册中心(如 ZooKeeper),不仅会增加注册中心的压力,还会因网络延迟影响调用效率。本地缓存正是解决这一问题的关键 —— 通过在客户端缓存服务地址,减少对注册中心的依赖,同时借助监听机制保证缓存与服务的一致性。

一、本地缓存的实现:客户端的 “地址速查表”

本地缓存的核心思路是:在 RPC 客户端维护一份服务地址的本地副本,调用服务时优先从缓存中获取地址,只有缓存未命中时才请求注册中心。

实现要点:

  1. 缓存载体:通常用哈希表(如 Java 的ConcurrentHashMap)存储,键为服务名,值为该服务的可用地址列表(如Map<String, List<InetSocketAddress>>)。
  2. 初始化加载:客户端启动时,从注册中心拉取所有服务的地址列表,初始化本地缓存。
  3. 查询逻辑:调用服务时,直接从缓存中获取地址(结合负载均衡算法选择一个地址),避免网络请求。
// 简化的本地缓存实现
public class LocalCache {
    // 服务名 -> 地址列表
    private final ConcurrentHashMap<String, List<InetSocketAddress>> serviceAddresses = new ConcurrentHashMap<>();

    // 从缓存获取服务地址
    public List<InetSocketAddress> getAddresses(String serviceName) {
        return serviceAddresses.get(serviceName);
    }

    // 初始化缓存(从注册中心拉取)
    public void initFromRegistry(Registry registry) {
        Map<String, List<InetSocketAddress>> allServices = registry.getAllServices();
        serviceAddresses.putAll(allServices);
    }

    // 更新缓存
    public void update(String serviceName, List<InetSocketAddress> newAddresses) {
        serviceAddresses.put(serviceName, newAddresses);
    }
}

二、缓存与服务的一致性:如何避免 “脏数据”?

本地缓存的最大挑战是 “缓存与注册中心的一致性”—— 如果服务地址发生变化(如节点上线、下线),本地缓存必须及时更新,否则会导致 RPC 调用失败(请求到无效地址)。

关键方案:基于 ZooKeeper 的监听机制

利用 ZooKeeper 的 Watcher 机制,可实现地址变化的实时感知:

  1. 注册监听:客户端初始化时,对注册中心中服务对应的节点(如/services/userService)注册 Watcher。
  2. 触发通知:当服务地址变化(如节点新增 / 删除),ZooKeeper 会异步通知客户端的 Watcher。
  3. 更新缓存:客户端收到通知后,重新从注册中心拉取最新地址,更新本地缓存。

 

三、核心价值与总结

本地缓存在 RPC 中的作用可概括为 “提速 + 减压”:

  • 减少对注册中心的请求次数,降低其负载;
  • 避免每次调用的网络延迟,提升 RPC 调用效率。

而 ZooKeeper 的监听机制则是一致性的保障 —— 通过 “主动通知 + 被动更新” 的方式,既保证了缓存的实时性,又避免了客户端轮询带来的资源浪费。

记住这一设计:本地缓存做 “速查”,监听机制保 “一致”,二者结合是 RPC 客户端高性能与高可用的基础。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值