提示:公众号展示代码会自动折行,建议横屏阅读


一、引言

CKV是腾讯自主研发的分布式内存KV存储系统,具备高性能、高可用,低成本等特性。从2009年上线至今,先后服务了空间、游戏、QQ、视频、音乐、微信、支付等诸多业务,与此同时,也为云上的用户提供高效、稳定的服务。
CKV在近一段时间,进行了一次较大规模的重构优化,本文将从新老系统以及自研与开源等角度进行对比,呈现系统的一些设计理念与解决方案。

二、背景

在当前互联网发展迅速,新技术层出不穷的时代,任何一款产品想要保持用户亲和度,且更具竞争力,通过重构的方式完成自我进化,是性价比较高的手段之一,特别是属于基础架构范畴的底层服务,如何应对业务场景变化,以及软硬件的迭代更新,如何在技术的大潮中站稳脚跟,自身都需要持续不断的提升。

系统重构的主要缘由通常分为两部分:解决业务遇到的实际问题;以及拓宽支撑的业务场景,服务更多用户。前者主要针对系统的可用性、可运维性、成本等诸多方面进行考量,从架构层面更加适应业务的高标准,高要求,同时,适应软硬件环境的变化,提升系统的可扩展性。后者则主要针对目前大多数用户使用习惯及业务形态的变化,提升系统易用性,可靠性及性能,同时兼容普及度较高的开源协议,从业务角度出发,解决社区版存在的一些问题,降低用户的运维成本与使用门槛。

三、架构进化

系统重构中,最直观的表现就是架构层面的演进,如何精简原有繁杂的各类模块,将耦合度高的流程进行整合,缩短数据流的关键路径,以及让整个系统管理更加精细化。

图1 系统模块组成,蓝色为新架构模块

如图1所示,系统在发展过程中,运维体系会越来越繁杂,其中包括各种不同功能的服务,对于系统的部署和维护造成了诸多不便,在重构过程中,我们将若干模块进行了精简与收敛。

图2 架构图

同时,CKV+从传统的三层架构,转为两层架构,如图2所示,将接入层的逻辑与存储层合并,有效降低了成本。同时,我们引入了可选的Proxy组件,能灵活兼容更多协议(如Memcached,ASN等)的同时,也使系统在一些特殊业务场景中(如业务链接数量较大,对接入层的平行扩展能力有较强需求等)更加游刃有余。
另一个较大变化则是线程模型,原CKV系统使用了网络IO与核心流程解耦的多进程模型,逻辑处理部分使用进程间加锁访问的方式,这种模型在性能、吞吐方面都有不俗的表现,但也存在两个较明显的缺点:1. 在硬件发展极快的前提下,为了提升硬件资源的利用率,逻辑处理模块需进行平行扩展,但加锁访问的模式会让用户请求的处理过程中出现较严重的毛刺现象;2. 由于网络处理与数据操作进行了解耦,对于一些基于网络的策略与流控,实现时的复杂度较高,且对性能有较大影响,而这部分功能的欠缺,会导致无法有效的提升系统隔离性。

图3 线程模型

重构后的CKV+则使用了单进程多线程的模型,将IO、内存引擎等逻辑模块聚合到同一个进程中,方便在多租户的环境中支持更多纬度的监控统计,以及订制更加细化的网络、CPU、磁盘等资源的管理策略。
当然,多线程也可能会带来一些潜在的问题,比如对于单条记录并行读写时,加锁仍会存在毛刺现象,IO是否会对核心引擎处理产生影响等。针对上述场景,我们也进行了调整,将同一个实例数据的读写操作进行收敛,让其在单个核上串行,其他CPU资源则负责IO,编解码等任务,让整个处理流程无锁,如图3所示。同时,引入了异步编程模型,利用异步IO等操作,将原本CPU消耗型的指令进行拆分,尽量减少毛刺,提升系统吞吐。
与原有系统相比,在功能场景方面,CKV+也有诸多改变。比如,在数据同步方面,新系统采用了流式传输,解决了原来同步流程容易产生瓶颈的问题;在跨地域方面,我们支持了主备分片的隔离策略可配置,以便支持业务跨机房容灾的场景;并开发了秒级回档,只读实例等提升用户数据安全的特性等。

四、自研与开源

在系统设计阶段,我们充分考虑到了当前各类用户的需求,以及业界的发展趋势,决定对Redis协议进行深度兼容。而选择Redis,主要因其作为KV系统,兼具协议简单易懂、功能用法丰富、核心功能稳定、应用场景广泛等优势。当然,Redis本身也存在一些缺陷和不足。因此,在充分发挥自研系统贴近应用场景,迭代快速等优势的前提下,我们希望为用户提供更强大,更好用的服务。
作为自研数据库,与原生Redis及一些基于原生的解决方案存在很多差异。对于很多Redis用户来说,CKV+最大的不同是多租户,即CKV+本身是一个分布式存储系统,且每个集群中存储了若干不同的业务数据,如图4所示。

图4 多租户模式

多租户可以更好的利用空闲资源,大大减少了重复的运维操作,也降低了单独维护大量进程实例的配置信息的人力成本,同时,可以更方便的对监控告警及统计信息进行收敛。
但部分云上的用户对此模式却存在一些疑惑,比如原生Redis单进程维护单实例的场景中,每个用户都可以订制自己服务的维护/升级时间,而多租户则无法做到业务纬度的独立升级;同时,用户对于不同实例间是否会相互影响,甚至产生资源争抢也存在疑问。

图5 热升级

我们在开发的过程中,也充分考虑到了用户的这些担忧,针对这些场景进行了优化改造。对于维护/升级,我们给出了更加彻底的解决方案,开发了热升级功能,如图5所示,在进程升级(替换)过程中,对于用户完全透明,无论长连接还是短链接,请求均可正常处理。这样不仅无需让用户再关注后台服务维护/升级的事宜,也解决了升级过程中,由于存量链接的中断,造成业务短时间受损的现状。
至于不同业务间相互影响的潜在风险,我们也做了大量工作。我们将一些利用内核实现的进程级别隔离方案(如cgroups等),在自身服务内部进行了实现,针对链接数、流量、内存使用量、磁盘容量、CPU使用率等都进行了隔离限制,同时支持实时的动态配置。
CKV+与原生Redis的另一个差异在于数据一致性。CKV+在最终一致的数据同步基础上,引入了基于Raft协议的强一致同步逻辑,为部分对于数据可靠性要求极高的业务提供更有保障的服务。
除此之外,在内存引擎方面,CKV+沿用了基于共享内存的数据管理方式,支持进程启动时,毫秒级的数据加载,避免服务异常恢复时对快照或流水的读写及解析。同时,我们对Redis通过Fork子进程生成快照的机制进行了优化,无需为每个实例预留一倍内存,从而避免了内存资源的浪费。

图6 内存引擎
在内存引擎方面,我们设计了一套具备自身特点的动态内存分配机制,避免初始化时系统预留过多资源,导致用户数据空间被占用等问题。同时,在共享内存中实现了Redis的复杂数据结构及各类语义。在内存使用率方面,较之原生也有更好的变现,如表1所示。

表1  1G内存实例中,随机样本存储对比

在引擎核心算法方面,我们也将会持续优化,做到在各种数据样本中,都能最大化利用内存资源,从而进一步降低用户成本。
除此之外,CKV+也继承了上一代系统的一些颇受好评的功能,如混合存储,将长时间没有访问的数据,转存到价格更低廉的介质上,数据的上浮下沉由系统基于既定规则自行触发,可极大的降低存储成本;以及CAS(Compare And Swap),在并发访问环境下,满足多客户端协同的需求等。
同时,我们在兼容Redis的各类功能时,也对齐进行了一定的优化和扩展,如集群版支持多DB,MGET/MSET不再受Slot限制等。未来,我们会持续推出更多更好用的功能,支持更多场景,也会对原生Redis欠缺的部分进行补充。
最后,开源与自研其实并非矛盾对立的两面,而是协同发展的关系,自研系统在借鉴、兼容开源的同时,也会推出许多更加方便,更贴近业务场景的功能,希望这些功能未来有机会被开源社区消化吸收,让更多用户受益。

五、效果

表2中对一些常用特性进行了横向对比,由于CKV+继承了原系统的部分场景,同时兼容了Redis的核心用法,因此,在易用性方面表现更好。

表2 特性对比

对于大家更关注的性能,由于Redis本身仅能使用单个核,因此在并发场景下的表现并不理想,而CKV+利用了多核优势,将请求流程中的网络IO、磁盘IO、编解码等非数据处理逻辑放到了所有核上,可获得较高的吞吐量,如图7所示。

图7 与Redis性能对比

而CKV+在处理ASN及Memcached协议时,单台Proxy的QPS可达到120万/秒,比原CKV提升了30%左右。

六、总结

CKV在若干年的开发运营中,服务了公司内外的众多产品,在慢慢壮大的同时,也暴露了许多不足。我们结合线上运营过程中遇到的问题及业务场景需要,对系统进行了全面的改造,将冗余的模块精简、收敛,重新打磨存储引擎,对普及度较高的开源协议进行了深度兼容,推出了更加贴近用户特性与用法,在易用性、可用性、可靠性、性能、成本等方面都有较大提升。
接下来,我们会持续对系统进行优化,对技术进行沉淀,希望能为更多用户提供更强大、更好用的服务。


腾讯数据库技术团队对内支持微信红包,彩票、数据银行等集团内部业务,对外为腾讯云提供各种数据库产品,如CDB、CTSDB、CKV、CMongo, 腾讯数据库技术团队专注于增强数据库内核功能,提升数据库性能,保证系统稳定性并解决用户在生产过程中遇到的问题,并对生产环境中遇到的问题及知识进行分享。

文章来源于腾讯云开发者社区,点击查看原文