多节点在不依赖外部组件的情况下。实现的方法有两种:
1. 如果节点不多,可以每个节点都保留一个副本,所有的时间线判断都在本地完成。
2. 如果节点比较多,可以采用分布式存储,当本地判断不存在时,需要广播所有的节点判断返回该时间线是否存在,然后更新统计计数。
因此筛选了3个java的组件,可用于实现节点之间的同步。
Atomix
atomix是基于事件驱动、有良好容错的分布式框架。支持集群管理,异步消息,分组,选主,异步并发控制,切片以及复制等功能。
提供了大量的分布式数据结构,例如:
AtomicValue
、AtomicCounter
、AtomicMap
、AtomicMuliteMap
、DistributedSet
、DistributedList
等等。
atomix本质还是采用c/s模式,这里的server是一个cluster,所有要先引导一个独立的集群。然后建立一个AtomixClient,设置cluster,即可与之通讯,使用分布式数据结构,发送消息队列。
infinispan
infinispan是一个分布式内存k/v数据存储。可以用java lib方式嵌入java服务中,也可以作为单独的服务提供远程接口。infinispan提供以下4种模式:
- Local: 只支持本地存储,不会和其他节点分享数据
- Invalidation caches: 该模式也不会分享数据,仅当数据失效时会通知其他的节点
- Replicated caches: 该模式下所有节点的数据会相互同步,适合读多写少的情形。
- Distributed caches: 分布式缓存数据,infinispan会帮你平衡数据,适合扩展。
infinispan是在jGroups上实现的,同时提供丰富功能:有效期、缓存上限、持久化、事务、查询和索引、事件以及对应的监听器。
jGroups
jGroups是一个可靠的消息工具,它通过创建一个集群让内部节点相互通讯。主要功能如下:
- 集群的创建与删除,集群节点间通过端口相互访问,支持节点的加入和删除。
- 探测成员的加入、离开以及碰撞并通知集群节点。
- 发送点对点消息,发送广播消息。
jGroups支持多种协议。相比前两种,jGroups只负责保证收发消息,使用起来也比较简单。
总结
-
atomix提供了各种丰富的组件,可以选主,也有消息传输。如果依托atomix实现时间线控制。可采用
atomix
+bloomFilter
+rocksdb
方式。实现如下:- 通过atomix选出主机器A,A机器保存最全的时间线
- 一条新的时间线T过来,本地判断T是否为新时间线,然后A机器判断是否为新时间线,确认为新时间线那就保存本地和hbase,同时通知A机器
- 判断时间线是否超过限制,可以通过A机器的计数决定。
- 时间线ttl就更加简单,直接在A机器开启定时器,扫描所有的时间线,通知所有节点和hbase清理时间线,其他节点需要每天更新的时间线时间同步到A机器,再由A机器同步至hbase
- 普通机器失效,直接将hbase数据同步至本地,连接上atomix集群即可
- A机器失效,atomix重新选主,系统暂停服务。等到将hbase的数据同步至新主服务再对外提供服务
- 缺点:A机器承担了判断时间线和同步功能,压力比较大。主服务器失效的情况下影响很大,时间线到期未清理同时主服务器失效可能会导致有些时间线一直得不到清理。
-
infinispan可以看成是redis的替代品,它就是一个内存k/v数据库。如果采用infinispan控制时间线,可以使用
infinispan
+bloomFilter
的方式实现。实现如下:- infinispan采用第4种方式,分布式缓存数据,保证集群有一定的副本。
- 判断时间线则先本地bloomFilter验证,直接infinispan验证,最后验证infinispan的总数,保证infinispan内存上数据是准确的
- 时间线ttl则让前端每天定时通过nginx发送一条消息,消息只会落到一台机器,就由这台机器清理infinispan上的时间线和hbase的时间线。最后返回前端,由前端通知所有节点重建bloomFilter。infinispan自带有效期和事件监听器,或许可以利用这一功能实现ttl,避免和前端交互。
- 如果infinispan集群的验证和遍历速度很快,那就可以省去bloomFilter。
- 缺点:节点少的情况,单个节点内存保存的数据量很大,机器集体失效的情况下,时间线写入时间数据会丢失。infinispan没有进行测试,目前不知道性能如何,能否扛住每秒6万的打击。
-
jGroups可以看成一个消息同步工具。采用就jGroup就需要使用
jGroups
+bloomFilter
+rocksdb
方式实现。实现如下:- 新的时间线过来本地判断。如果本地判断为新时间线,则发送至jGroup集群,通知所有节点,接收到消息的节点则经过判断本地是否存在之后则保存至bloomFilter和rocksdb。
- 所有的节点同时也需要记录下每天更新了数据已存在时间线,然后定时通知其他节点,保证所有节点的时间线的时间每天都有更新
- 前端每天定时发起清理时间线请求,收到请求的机器则清理本地时间线和hbase时间线,通知其他节点清理时间线,重建bloomFilter。
- 缺点:所有节点都要相互通知,io请求比较多。每个节点都保存最全的数据,有可能会出现不一致情况。每天ttl清理时间线,重建bloomFilter期间,数据判断可能出现问题。