美团万亿级kv存储架构学习

参考链接:https://tech.meituan.com/2020/07/01/kv-squirrel-cellar.html

KV 存储作为美团一项重要的在线存储服务,承载了在线服务每天万亿级的请求量。在 2019 年 QCon 全球软件开发大会(上海站)上,美团高级技术专家齐泽斌分享了《美团点评万亿级 KV 存储架构与实践》,本文系演讲内容的整理,主要分为四个部分:第一部分讲述了美团 KV 存储的发展历程;第二部分阐述了内存 KV Squirrel 架构和实践;第三部分介绍了持久化 KV Cellar 架构和实践;最后分享了未来的发展规划和业界新趋势。

一、美团点评KV存储发展历程

美团点评第一代kv存储如下:

在这里插入图片描述

上述memcached方案的问题是,在节点故障从技术摘除时,会丢数据;当需要扩容时,一致性哈希也会丢数据。

随着redis的成熟,从memcached换成了redis,客户端仍用一致性hash,服务端变成了redis主从结构,当一个主节点宕机,redis通过哨兵模式完成failover,用选举一个从节点自动替代主节点,以此实现高可用。但如果扩容的话,一致性hash仍会丢数据,怎样解决呢?
其实这里可以用redis cluster集群模式解决,当时2014年,可能还没有redis cluster?

这里,美团发现了阿里的一个成熟开源Tair。
在这里插入图片描述

Tair的架构主要分三个部分:存储节点会上报心跳到他的中心节点,中心节点内部有2个配置管理节点,用来监控所有的存储节点。当有任何存储节点宕机或者扩容时,他会做集群拓扑的重新构建。当客户端启动时,他会直接从中心节点来拉取一个路由表,路由表就是一个集群的数据分布图,客户端根据路由表直接去访问可用的存储节点。针对之前KV的扩容丢数据问题,他有自己的数据迁移机制来保证数据不丢。
说明:这个过程做的明显不如redis cluster好啊。

在美团实际使用时,发现了一些问题,如中心节点虽然是主备高可用的,但实际上并没有类似于分布式的仲裁机制,在网络分割情况下,他有可能发生“脑裂”。另外,在扩容时,数据迁移也可能影响业务的可用性。且Tair相比于redis,其数据结构不那么丰富,所以Tair不能完全满足业务需求。最终,美团在Tair开源之上进行自研。

在2015年,redis官方发布了redis cluster。美团跟随redis社区,并结合内部需求,演进出了全内存的KV存储Squirrel。
另外,基于Tair, 美团加入了些自研功能,演进出了可落地的KV存储Cellar。因为Tair已经4,5年没更新了,所以Cellar的迭代全靠自研。

二者选型差别:如果业务数据量小,对延迟敏感,建议用Squirrel;如果数据量大,对延迟不是特别敏感,建议用成本更低的Cellar。目前两套KV存储系统每天调用量均已突破万亿,请求峰值也突破了每秒亿级。
在这里插入图片描述

二、内存KV Squirrel
2.1、Squirrel简介
对于Squirrel, key怎样分不到存储节点上的呢?还是根据key,用固定的hash算法计算出hash值,然后对slot数目取模,得到一个slot id, 然后这两种KV都是预分片16384个slot。得到slot后,在根据理由表就能查到这个slot存储在哪个节点上。
说明:这个步骤跟redis cluster完全一样。
在这里插入图片描述

 Squirrel架构:

在这里插入图片描述

中间部分跟redis官方集群一致,他有主从结构,redis实例之间通过gossip协议通信。只是加了一个管理后台,用于实现服务调度、扩缩容、高可用等。他会去管理集群,把管理结果作为元数据更新到zk,客户端订阅zk上的元数据变更,这样客户端可实时获取到集群的拓扑状态,直接在redis集群上进行读写操作。
说明:这样有必要么?redis cluster本身就会跟redis集群通信,美团这么干绕了一圈,增加了依赖,没看出好处。

2.2、Squireel容灾
对于redis集群而言,节点宕机已经有完毕的机制了。官方提供的方案,任何一个节点从宕机被标记为FAIL摘除,一般需要经过30秒。主库的摘除可能会影响数据的完整性。

Squireel的架构如下图:
他会实时监控集群中的所有节点,不管是网络抖动,还是节点宕机,他都会实时更新zk, 客户端收到消息后,读流利会自动进行转发。假设redis2只是几十秒的网络抖动,过几十秒后,HA节点监控到他恢复后,会把他重新加回。
在这里插入图片描述

说明:这点方案,没看出哪比redis强,redis单个节点瞬时不可用,可以通过redis客户端重试解决。

如果过了一段时间,HA判断他属于永久性宕机,HA节点会直接从k8s集群申请一个新的redis4实例,把他加到集群里。此时,拓扑结构又变成了一主两从的标准结构,HA节点更新完集群拓扑后,就会去写zk通知客户端更新路由,客户端就能到redis4这个新从库上进行读操作。

通过上述方案,从库的摘除时间从30秒降低到5秒。另外,我们通过HA自动申请容器实例加入集群的方式,把宕机补副本变成了一个分钟级的自动操作,不需要人工介入。

问题:从库发现时间,必须要30秒么?redis也是可配置的。美团的方案未发现特别之处。

2.3、Squirrel跨地域容灾
跨地域容灾有哪些特点?
1、相对于同机房而言,跨地域专线可能不稳定
2、跨地域专线的带宽是有限且昂贵的

在这里插入图片描述

异地多活:北京&上海,北京部署主集群,上海部署从集群,一主两从

这里实现异地数据同步,主要通过集群同步服务,把北京主集群的数据同步到上海从集群上。
同步流程:首先向同步调度模块下发“在两个集群间建立同步链路”的任务,同步调度模块会根据主从集群的拓扑结构,把主从集群间的同步任务下发到同步集群,同步集群收到同步任务后,会伪装成redis的slave, 通过redis复制协议,从主集群上的从库拉取数据,包括RDB及后续的增量变更。同步机收到数据后,把他转成客户端的写命令,写到上海从集群的主节点里。
说明:没什么特别的,就是伪装成redis slave做数据同步。
2.4、Squirrel智能迁移

 在这里插入图片描述

没什么特别的,就是redis migrate命令,对于bigkey, 使用了异步执行migrate命令 

2.5、总结

暂时没看出Squirrel比redis cluster强在哪

三、可落地KV Cellar

3.1、Cellar的架构

 在这里插入图片描述

跟阿里Tair有两个不同:一是OB,二是Zookeeper。OB起到Zookeeper的Observer的作用,提供Cellar中心节点元数据的查询服务,他可以实时与中心节点master同步最新的路由表,客户端的路由表都是从OB去拿。这样做的好处:
1)把大量客户端跟集群的大脑Master做了隔离,防止路由表的请求影响集群的管理
2)因为OB只用于做路由表查询,所以他可以水平扩展。
另外,通过引入zookeeper来做分布式仲裁,用来解决master, slave在网络分割情况下的“脑裂”问题,并通过把集群元数据存储到zk,保证了元数据的高可靠。

3.2、Cellar节点容灾
一个节点宕机通常是临时的,一个节点网络的抖动也是临时的,他们会很快的恢复,并重新加入到集群。不该因为节点临时出问题就把他从集群摘除,美团实现了Handoff机制来解决节点短故障带来的影响:

在这里插入图片描述

如上图所示,如果A节点宕机了,会触发Handoff机制,这时中心节点会通知客户端A节点发生了故障,让客户端把分片1的请求也打到B上,B处理完客户端的读写请求后,还会把应该写入A节点的分片1&2 数据写入到本地的log中。

如果A节点宕机后3~5分钟恢复了,A节点就会上报心跳到中心节点,中心节点就会通知B节点“A节点已经恢复了,你把他不在期间的数据创给他”,这时,B会把本地存储的log回写到A节点上。当A拥有了故障期间的全部数据之后,中心节点就会告诉客户端,A节点已经彻底恢复了,客户端就可以重新把分片1的请求打回给A节点。

通过这样的操作,可以做到秒级快速节点摘除,而节点恢复后加回,只需要补齐少量的增量数据。另外如果A节点要升级,中心节点就先通过主动

说明:handoff方式相比于redis主节点故障,从节点顶上的方式,看起来故障对业务影响更小,因为redis不能轻易判定主节点故障,因为主从切换是需要代价的。这点上美团做的不错。
 

 3.3、Cellar跨地域容灾

Cellar跟Squirrel面对的跨地域容灾问题是一样的,解决方案同样也是集群间复制。

在这里插入图片描述

上图以北京主集群,上海从集群为例实现跨地域容灾:客户端写操作到写到北京主集群A节点,A节点会通过集群主从复制把数据复制到B和D,同时A节点会把数据复制到从集群的H节点。
在H节点完成集群间写入复制后,他也会做集群内复制,把写操作复制到从集群的I、K节点。

3.4、Cellar强一致
由于数据复制是异步的,可能因为故障节点数据还没复制出来,导致数据丢失,这对于金融支付场景,是不允许的。业界主流的解决方案是基于Paxos或Raft协议的强一致复制。美团最终选择了Raft协议。
在这里插入图片描述

说明:这个应该就是抄的Redis的做法。

从上图可以看到,slot1在存储节点1,2,4上,slot2在存储节点2,3,4上。每个slot组成一个Raft组,客户端会去raft leader上进行读写。由于预分配了16384个slot,所以在集群规模很小的时候,一个存储节点上可能会有数百上千个slot。这时候如果每个raft复制组都有自己的复制线程、复制请求和log,那么资源消耗会非常大,写入性能也差。所以美团做了multi raft实现,Cellar会把同一个节点上所有的raft复制组写一份log,用同一组去做复制,不同raft组间的复制包也会按照目标节点做整合,以保证写入性能不会因raft组过多而变差。raft内部其实有自己的选主机制,他可以控制自己的主节点,如果有任何节点宕机,他可以通过选举机制选出新的主节点。
3.5、Cellar智能迁移

 在这里插入图片描述

上图是Cellar智能迁移的架构图。slot的迁移分成三个状态。第一个状态是正常的状态,没有任何迁移。这时要把slot2从A节点迁移到B节点,A会先给slot2打一个快照,然后把这个快照全量发给B节点上。在迁移数据的时候,B节点的回包会带回B节点的状态。B的状态包括什么?引擎的压力、网卡流量、队列长度等。A节点会根据B节点的状态调整自己的迁移速度,他经过一段时间的调整后,迁移速度会达到一个平衡,达到最快速的迁移,同时又尽可能小地影响业务的正常请求。

当slot2迁移完后,会进入图中slot3的状态。客户端这时可能还没更新路由表,当他请求到了A节点,A节点会发现客户端请求错了节点,但他不会返回错误,他会把请求代理到B节点,然后把B的响应再返回给客户端。同时他告诉客户端,需要更新一下路由表,伺候客户端就能直接访问到B节点了。

说明:这个过程跟redis有稍许不同:redis是请求A节点,发现不在A,则A节点返回客户端,告诉他应该去B上取,然后客户端去B上取,并更新路由表。
3.7、Cellar热key

在这里插入图片描述

美团对待热点key时,不像redis那样把热点所在的slot做迁移到新的节点,而是把热点key复制到指定的节点,也就是图上的C、D节点。通过这样的方式,可以只对热点数据对应的节点做扩容。 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值