人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

背景

经过几年的努力,58同城已经自研了4款分布式存储产品。分别是Key-Value、Key-List、对象存储、共享文件系统。其中分布式Key-Value存储WTable是最早开发的,在集团内使用最为广泛,甚至对象存储与共享文件系统都是用WTable来存储Meta信息。WTable的开发大致上可以分成三个阶段,2015年发布第一版,满足了业务的核心需求。第二阶段重点优化了读写性能与请求延迟,提高运维自动化与速度。第三阶段从2019年开始,分步引入NewSQL的相关技术,为业务提供更人性化与更高效的使用体验。

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

WTable第一阶段

在WTable之前58存储主要使用MySQL+Cache。当数据量太大时需要做分库分表,若数据增量又很大就需要定期做扩容,非常耗时费力。因此对WTable的核心需求总结为:扩容、可用性、高性能、扩展能力。为了简化架构,在设计上引入了两个外部组件:ETCD用作配置中心与多副本选主,Rocksdb作为数据节点的存储引擎。通过代理服务层对请求进行路由,存储节点以Group为单位,每个Group中通常是一主两备,主备之前通过异步实时同步来保持数据最终一致。

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

WTable将数据分成2048个Slot,Key哈希之后对2048取模,作为该Key所属的Slot。Proxy本地缓存着每个Slot所属的Group以及每个Group的存储节点列表。当请求到来时根据Slot将请求转发到后端的存储节点。当存储空间不够或者写性能不足时可以通过增加Group方式来扩展。

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

为了应对各种异常,WTable使用了多级容灾策略。首先客户端会定期从NameCenter拉取Proxy列表以感知Proxy的列表的更新。取到列表之后每2秒会检测Proxy是否正常,若多次检测异常则会将其加入黑名单。Proxy也会检测后端存储节点。如果Master角色异常则会通过ETCD自动选举新的Master,若是Slave异常自动被Proxy屏蔽。

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

为了尽可能提高KV使用的灵活性,WTable还提供了丰富的操作接口,如,乐观锁,自动过期等,而且对其中大多数接口都提供了批量操作支持。从2015年上线至今,线上几十个集群,存储着有百T的数据量,日请求量达到三千亿,为一千多个业务提供服务。

WTable第二阶段

第二阶段主要通过研究Rocksdb来获取性能的提升以及运维速度的提高。首先将Rocksdb版本从3.11升级到5.15,并且对Rocksdb参数进行优化,读写性能与延迟都有很大的提高。当写入量大时,底层Compaction会阶段性地产生IO峰值。在这些IO峰值处,读写延迟会变高。经过调研,Rocksdb有成熟的Comapction限速方案。通过设置AutoTune以及磁盘IO上限能够自适应Compaction与写入量的关系。

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

运维主要涉及换机器时的加备机,磁盘空间不够时的扩容操作。原先这两个操作速度较慢,在应对一些突发情况时比较捉急。加备机操作原先的方法是在主机上创建迭代器,把KV遍历出来依次写到新备机。瓶颈出现在KV的遍历上,因为这个操作非常耗IO,快了会影响线上服务,因此必须限速。另外由于迭代器没有及时释放可能会出现为了加备机导致主机磁盘空间告警的悲剧。经过调研,其实Rocksdb提供了Checkpoint这种非常友好的数据同步方式。得益于LSM存储结构中的SST写入后不会被修改,因此Checkpoint只需要为当前版本所有SST文件创建硬链即可,整体耗时只需要几百毫秒。创建完成之后,发送SST文件到新备机,几乎不消耗IO,瓶颈只剩下网络带宽了,对于万兆网卡的机器,速度可以轻松达到三五百兆。

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

集群的扩容涉及到数据的迁移,WTable的扩容以Slot为单位进行。当增加一个Group之后,通过Manager服务会计算好每个Group需要承载的Slot个数,然后制定迁移计划,按照Slot进行迁移。每完成一个Slot迁移相应更新ETCD中的路由配置信息。但是这种方式有一个瓶颈就是在迁移的过程中,前面迁移的Slot已经提供线上服务。新的Slot迁移会有大量数据写入,会影响线上服务。例如:总共有8个Slot需要迁移,当迁移第5个Slot时前面四个Slot已经提供线上服务。

为了避免这种影响,不再以Slot为单位进行数据迁移,而是将所有待迁移的Slot作为一个整体进行。接上例:先对这8个Slot做全量同步,然后对这8个Slot做增量同步,最后修改ETCD中的路由信息。数据扩容完成之后需要从原Group中删除,以释放空间。原删除是遍历出Key,然后依次删除,非常消耗IO,而且速度很慢。现在优化成先通过DeleteFileInRange接口把完全处于待删除Key范围的SST文件直接删除,然后通过CompactRange+CompactFilter组合把剩余的数据删除。整体耗时非常短,IO消耗非常低,达到及时释放存储空间的目的。

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

WTable第三阶段

第三阶段,目的是引入NewSQL相关技术提高WTable的使用效率。第一步就是提供强一致性版本。为了实现强一致,需要使用一致性协议。最初计划是使用ETCD中的Raft实现,将其修改成MultiRaft。后来发现有一个DragonBoat开源库,其有非常高的测试覆盖率以及读写性能。经过实际测试,在有足够并发时其整体吞吐量相对于异步复制高,但是每个请求延迟也相对较高,因为需要走一遍Raft协议流程。

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

在强一致性版本中尽量保持了原先的设计,依然保持2048个Slot,每个Slot的数据通过一个RaftGroup来实现同步。而这个Slot多副本的分布则在整个集群内自动均衡。原先的固定主备关系已经不存在,Leader的选举也不再需要ETCD,因为每个RaftGroup自动会选举Leader。在Proxy中依然缓存着路由信息,并通过ETCD来实时更新。

扩容时只需要增加机器即可,WTable会自动计算每台机器应该承载的Slot个数,并做数据迁移。扩容过程首先将节点以Observer方式加入到RaftGroup中开始做数据同步。当数据同步完成之后将该节点提升为Follower,并更新ETCD中的路由信息,接着去所有Proxy确认信息已经更新。然后把一个老节点从ETCD的路由信息中移除,再去Proxy确认。最后才将该节点真正从RaftGroup中移除。通过这两次确认可以保证路由信息的准确。

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践

目前强一致性版本的WTable已经开发完成,后面计划开发分布式事务。对于KV类的存储,分布式事务的支持能够很好地提高业务数据的逻辑一致性。最后在WTable基础上支持常用的SQL语法,这些都已完成,实际上可以算是一个简化版的NewSQL了。



总结

每个系统在设计阶段会有很多变量,需要充分考虑业务核心需求与痛点以及当前可用资源后做出权衡,最终得到一个业务可接受、资源消耗可控的设计。WTable的迭代过程,就是平衡各方面因素的结果。第一阶段重点解决容灾、高性能等核心需求,但是在集群运维方面有很多不足,第二阶段重点解决了这些问题,第三阶段考虑如何提供更好的用户体验。一个好的系统总是慢慢进化而来,相信WTable未来会更好用,更高效。

谢谢大家!

人物|钟昌寿:58同城分布式存储系统架构设计和优化实践


欢迎大家关注“58技术”微信公众号,“58技术”是58官方技术号,58技术创新、分享与交流平台。


分享到:


相關文章: