分布式本地缓存的一种实现

来源:互联网 发布:国外电视台直播软件ios 编辑:程序博客网 时间:2024/05/22 12:21
  • 源代码

Java SDK:https://github.com/gilbertwang1981/string_local_cache.git

C++ Agent:https://github.com/gilbertwang1981/binary_log_agent.git

C++公共库:https://github.com/gilbertwang1981/commonlib4c.git


  • 背景
过去一年公司核心系统重构中,有些应用场景是需要使用到本地缓存的,当本地缓存的数据发生更新(删除/增加/修改/全量刷新),如何通知到同一个集群中其他进程更新本地副本,确保同一个集群中,每一个进程实例的地址空间的数据是一致,保证实效性。现在市面上可选用的开源的本地缓存也非常之多,比如Guava的LoadingCache等。这些数据的有效性一般是通过过期-回源的方式来实现的,并不是跨进程的数据增量复制来保证各个业务进程的本地缓存数据一致。在这里,我们实现了后一种方式的数据同步,也是一种去中心化的架构。

  • 设计思想
分为两大核心层:
  1. 第一层为数据缓存层,原则上可以选用任意第三方本地缓存组件,这一块不是我们的重点,在我们的实现中,选用了Guava的LoadingCache。
  2. 第二层为数据复制层,这一层是我们的重点,我们要解决跨进程的数据复制,确保同一集群中各个进程实例地址空间数据副本的一致性,网络节点监控以及服务发现等能力。


采用JAVA实现本地缓存的SDK,因为在实际应用中,我们的所有业务系统都是Java编写的。确保JAVA SDK尽可能少的和应用争抢资源,尽可能少的占用系统资源。JAVA SDK在缓存层对第三方缓存组件做了简单的封装,将二进制日志通过SDK写入本地共享内存,共享内存被建模为一个基于PROTOBUF 3协议的本地小型数据库。JAVA SDK只会负责向数据库中写入BINGLOG。



本地Agent进程,负责消费共享内存数据库中的数据,并对日志进行跨进程复制和重放。Agent同其他节点的业务进程(JAVA SDK)之间建立TCP长连接,用于数据复制,当业务进程(JAVA SDK)接收到请求之后,直接更新本地缓存。共享内存中的数据是持久化到磁盘的,应用可以从任何一个db文件以及该db文件的offset开始重放,能够确保数据不丢。




Agent进程之间,使用组播实现自适应网络,任何Agent或者第三方节点都可以join&leave这个网络而不需要额外的配置,任何第三方系统也可以加入并监听组播网络中的消息实现网络管理功能。当有新的Agent节点加入后,集群中的Agent节点将自动感知到,并且能自动获取即将加入节点的地址,其他节点的Agent可以自动增加到即将加入节点的业务进程TCP长连接(Agent到JAVA SDK的TCP长连接)。当有节点退出,组播网络也能广而告之,该节点将自动从集群中移除,从而实现自管理。



在数据复制过程中,如果一条数据通道(TCP长连接)发生异常,本地的Agent将通知到本地的JAVA SDK,通过回调告知应用(Agent通知JAVA SDK,带上无法复制的key&value),某台服务器的本地缓存可能没法同步到,数据不一致即将发生,应用可以采取一些措施。同时,Agent也会通过组播网络告知集群中的其他节点或者第三方监控节点,数据一致性可能存在问题并发出alarming。

在这套体系中的所有IPC统一采用PROTOBUF 3二进制编码(包括:共享内存,复制协议,服务发现协议等)。同时,Agent到各个业务进程(JAVA SDK)的TCP长连接有重连机制。当TCP因为网络问题闪断,能保证2秒内重连恢复。

  • 共享内存数据结构
包括:索引和数据两部分。



  • 下一步演进

数据复制只会在Agent之间进行,由本地的Agent通过UDP实现回调通知到本地的JAVA SDK。



原创粉丝点击