一.问题描述
最近思考了下,在分布式系统的一致性方面,有几个系统很有意思。
一致性包括读写两方面。读的一致性,和写的一致性,在存储系统中体现的不一样。
因为在使用场景中,因为场景需要,各个分布式系统,实现的结果/支持的特性也不一样。比如数据库、消息系统、缓存、搜索系统、文件系统、注册服务发现系统。这些系统因为要支持其对应的场景,实现的结果也不一样。
二.举例子
举例子,就举几个有趣的例子。
1.consul的一致性读和kafka的一致性写。
很有趣,consul的读,get 一个key from consul cluster。 支持3种:
a.读follow。client读consul cluster中 一个follow 结点就可以返回。
b.读leader。从leader结点读,能保证相对一致。(如果网络分区/选主期间/选主前期就不一致了)
c.读所有结点。从所有node读数据,都一致则返回给client。这个能保证强一致。
所以,consul 在读一致上,刻意这么做给client更多选择。来做读取速度、一致性、并发吞吐量 上 做权衡。
而kafka 的 publish msg(写消息)。正好与consul的读类似。也可以分3种:
a.client publish msg 到 server cluster 的一个结点,就返回。(如果topic 做了多个partition,以partition为单位对应broker)
b.写成功m个节点。
c.写成功all 个节点。
所以很有趣,consul 读支持3种,kafka 写支持3种。
2.rabbitmq 集群。
rabbitmq集群的有趣之处是:
a.生产msg 可以直接 publish到 leader or follow 结点。
b.消费 msg ,必须 要 从leader上消费。
c.如果出现网络分区,follow要被踢出cluster。
d.为了防止循环写入,rmq 实现了 a->b->c->d->a 环形同步。
e.rabbitmq的消费msg,是强一致的。必须cluster中存活的node都消费完msg,才server response ack to client。
3.es和kafka 集群。
es和kafka 的特别之处是,在数据存储上,支持数据分片。
a.es叫 shard,kafka叫partition。
b.es把一个index 拆分成多个shard,一个shard对应比如3个副本,一个副本可以用1个节点,可以部署9个节点,打散分片和index。
c.kafka把一个topic拆分成多个partition,一个partition可以有3副本,个副本可以用1个节点,可以部署9个节点,打散分片和topic。
d.es可以对index按照时间再拆分/归档,比如jaeger的es索引,包含trace,span,就按天建index。
4.redis cluster 与consul 无中心化和有中心化
a.为了解决 集群的结点的状态信息,做信息交换数据同步,都用gossip。无中心化。
b.而集群内,存储数据/server层结点的数据同步,redis 用 异步replication,consul用 raft。有中心化。
c.选主的逻辑都类似。得用gossip。依靠更多结点参与。以保证少数服从多数。极端例子就是,如果client不认可这个server为新主,但其他server认可这个node为新主,这样就没意义了,因为client连不上这个server,这个新主选出来就没意义。
5.三层网络集群问题
这个在redis cluster, consul,特别是 client cluster -> proxy cluster -> server cluster 这种架构中存在。
a.client 之间,proxy 之间,server 之间,各自组成一个集群网络。相当于3个集合 C-set, P-set, S-set
b.上面 C-set 和 P-set 之间要通信,所以又组成一个网络。 C-set----P-set
c.上面 P-set 和 S-set 之间要通信,所以又组成一个网络。 P-set----S-set
这就很复杂了,如果网络/集群状态发生变化,如何选新leader,这要保证新leader被大多数结点认可。
6.数据复制
有的集群复制是串行,a->b->c ,有的是 a->{b,c}
a.hdfs 和 rabbitmq 集群,就是 第一种。
b.mysql ,redis,kafka,zookeeper,consul ,es 就是第二种。
c.paxos比raft就更复杂了。
以上几个问题,很有趣。
遗留个问题,redis cluster 的双机房双向同步,不改源码,不好做。