美文网首页
架构师方案-本地缓存一致性刷新方案

架构师方案-本地缓存一致性刷新方案

作者: 香沙小熊 | 来源:发表于2023-11-30 17:49 被阅读0次

    前言

    本地缓存和业务请求在同一台机器上,相对于Redis读写速度非常快,对于一些变更频率低、实时性要求低的数据,可以放在本地缓存中,提升访问速度。 使用本地缓存能够减少和Redis类集中式缓存间的数据交互,减少网络I/O开销,降低这一过程中在网络通信上的耗时,同时减轻对Redis类集中式缓存访问压力。

    image.png

    解决方案

    服务是多节点部署的,要保证是本地缓存一致性的,就要短时间内操作所有服务。

    方案1-MQ广播消息

    image.png
    redis发布订阅功能实现同理

    方案2-Zookeeper Watcher机制

    image.png

    Tomcat Watcher监听

    @Service
    public class ZkDataListenerImpl implements IZkDataListener {
        @Override
        public void handleDataChange(String dataPath, Object data) throws Exception {
            String type = getType(data);
            if (type.equals("update")) {
                //更新缓存
           
            }
            if (type.equals("delete")) {
              //删除缓存
            }
        }
    
    }
    

    方案3-RPC框架广播调用(如dubbo广播调用方式)

    image.png
    <dubbo:service cluster="broadcast" />
    

    实现逻辑

    1. 循环调用所有的实例
    2. 如果有发生异常则记录异常保存
    3. 只要有异常,则抛出异常,如果没有则返回执行结果

    源码

    public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
    
        private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class);
    
        public BroadcastClusterInvoker(Directory<T> directory) {
            super(directory);
        }
    
        @Override
        @SuppressWarnings({"unchecked", "rawtypes"})
        public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
            // 检查 invokers 是否为空
            checkInvokers(invokers, invocation);
    
            // 将invokers 塞到context中
            RpcContext.getContext().setInvokers((List) invokers);
            RpcException exception = null;
            Result result = null;
    
            // 遍历invokers 执行, 结果只要最后一个不报错的result
            for (Invoker<T> invoker : invokers) {
                try {
                    result = invoker.invoke(invocation);
                } catch (RpcException e) {
                    exception = e;
                    logger.warn(e.getMessage(), e);
                } catch (Throwable e) {
                    exception = new RpcException(e.getMessage(), e);
                    logger.warn(e.getMessage(), e);
                }
            }
            // 如果出现一个异常,  抛出异常
            if (exception != null) {
                throw exception;
            }
            return result;
        }
    }
    
    

    方案4-分布式任务调度的广播执行任务

    广播执行表示一个任务实例会广播到该分组所有Worker上执行,当所有Worker都执行完成。

    方案对比

    方案 特点
    MQ广播消息 有消息积压、消息顺序的问题
    Zookeeper Watcher机制 Zookeeper本身适合读多写少的场景
    RPC框架广播调用(如dubbo广播调用方式) 循环调用所有的实例,所有要考虑实例过多的情况
    分布式任务调度的广播执行任务 便于定时发布

    总结

    从以上这些方案,不难看出,只要有广播功能特点的中间件或服务,都可以用来操作本地缓存或者本地方法。

    相关文章

      网友评论

          本文标题:架构师方案-本地缓存一致性刷新方案

          本文链接:https://www.haomeiwen.com/subject/ktvqgdtx.html