从Redis7.0的发布看Redis的过去和未来它不仅包含了50多个新命令,还有大量的核心新特性和改进,不仅可以解决用户使用中的诸多问题,还可以进一步拓展Redis的使用场景。尽管Redis7.0做了很多大胆的尝试,但稳定性仍然是最重要的基石。Redis官方在7.0GA博文中也强调了这一点:“虽然面向用户的特性很容易吹嘘,但这个版本真正的‘无名英雄’是努力让Redis更高性能、更稳定、更精简。”(虽然面向用户的特性更容易被点赞,但是这个版本的无名英雄是我们对Redis持续的优化,让它更精简、更高效、更稳定)相信从这里可以看出Redis的稳定性一直以来都被放在最重要的位置,7.0稳定性的担忧可以打消,下面就跟随我们一起了解一下Redis7.0的几大核心新特性吧,Redis7.0核心新特性概览Function是Redis脚本方案的新实现,在Redis7.0之前,用户只能使用EVAL命令族来执行Lua脚本,但是Redis对Lua脚本的持久化和主从复制一直是未定义的,各个大版本甚至release版本也有不同的表现,因此社区也直接要求用户在使用Lua脚本时,在本地保存一份(这也是最安全的方式),以防止Lu??a脚本可能丢失e由实例重启和主从切换引起。在Redis中维护Lua脚本一直是广大用户的痛点。Function的出现是对Lua脚本很好的补充。它允许用户将自定义函数库加载到Redis。一方面,用户定义的函数名称可以比EVALSHA调用方法具有更清晰的语义。另一方面,Function加载的函数库会明确的进行主从复制和持久化存储,彻底解决了以往Lua脚本在持久化方面存在歧义的问题。那么从7.0开始,Function命令族和EVAL命令族有了自己明确的定义:FUNCTIONLOAD会自动进行函数库的主从复制和持久化存储;而SCRIPTLOAD不会进行持久化和主从复制。只保存在当前执行节点上。并且社区也在计划在后续的版本中让Function支持更多的语言,比如JavaScript、Python等,敬请期待。总的来说,Function在7.0中被设计成数据的一部分,因此可以保存在RDB和AOF文件中,并且Function也可以通过主从复制的方式从主库复制到所有从库,可以有效解决之前的Lua脚本缺失问题,我们也强烈建议大家逐步将Redis中的Lua脚本替换为Function。Multi-partAOFAOF是Redis数据持久化的核心解决方案。它的本质是不断的为数据修改操作添加重做日志。由于是连续添加,所以需要进行回收,即compaction,在Redis中称为AOFrewrite。但是,如何处理AOFrewrite过程中的增量数据,一直是个难题。以往rewrite期间的增量数据需要保存在内存中。重写结束后,将这部分增量数据写入新的AOF文件中,保证数据的完整性。.可见AOFrewrite会额外消耗内存和磁盘IO,这也是RedisAOFrewrite的痛点。虽然之前已经做了很多改进,但是资源消耗的本质问题并没有得到解决。阿里云的Redis企业版一开始也遇到过这个问题。经过内部开发的几次迭代,实现了Multi-partAOF机制来解决。同时也贡献给了社区,并随着这次7.0版本发布。具体做法是采用base(全量数据)+inc(增量数据)独立文件存储方式,彻底解决内存和IO资源的浪费。同时还支持历史AOF文件的保存和管理。结合AOF文件中的时间信息,可以实现PITR时间点恢复(阿里云企业版Tair已经支持),进一步增强了Redis的数据可靠性,满足了用户数据回滚的需求。Sharded-pubsubRedis从2.0开始支持发布订阅机制。pubsub命令家族的用户可以轻松建立消息通知订阅系统。但是Redis集群模式下的pubsub存在一些问题。广播风暴即将来临。Redis的pubsub是根据channel频道进行发布和订阅的。但是在集群模式下,channel不被当做数据对待,即不会参与hash值的计算,也不能按照slot进行分配。因此,在集群模式下,Redis采用用户发布的消息在集群中广播的方式。那么问题就很明显了。如果一个集群有100个节点,用户在节点1的频道上发布消息,则该节点需要将消息广播给集群中的其他99个节点。如果只有少数其他节点订阅了channel通道,大部分消息都是无效的,造成网络、CPU等资源的极大浪费。Sharded-pubsub就是用来解决这个问题的。顾名思义,sharded-pubsub会根据分片来分配频道。一个分片节点只负责处理自己的频道,不广播,用很简单的方式避免了。浪费资源。Client-evictionRedis支持内存规格配置。maxmemory和maxmemory-policy大家都很熟悉了,这里还是要说明一下:maxmemory控制的是Redis整体的运行内存,而不是数据内存,比如clientbuffer和luacache,fucntioncache,dbmetadata等都会计算在运行内存中。如果运行内存超过maxmemory,会触发evict删除数据。这也是用户在使用Redis时的一大痛点。在这些非数据内存使用中,客户端缓冲区消耗最多。在大流量的情况下,客户端需要缓存大量的用户读写数据(想象一下,keys的结果需要先缓存在客户端输出缓冲区,然后再发送给用户)。流量的内存消耗在很多情况下会导致触发驱逐删除数据。Redis虽然很早就支持了client-output-buffer-limit配置项,但只是限制了单个连接维度的输出缓冲区,并没有全局统计client使用内存和限制。为了解决这个问题,7.0增加了maxmemory-clients配置项来限制所有客户端使用的内存。如果超过此限制,将选择并释放内存消耗最大的客户端以减轻内存消耗。Client-eviction不是终点,大量元数据的内存占用会给用户带来困扰。Redis是一个基于内存的数据库。我们需要对各个模块的内存进行更加准确的统计和控制,让用户能够有效的存储数据。更清晰的理解和规划。Redis历史回顾Redis发展至今经历了7个大版本,每个大版本都有大量的新特性。比如从3.0开始支持cluster集群模式;4.0开发的lazyfree和PSYNC2解决了Redis长期大key删除阻塞问题和同步中断无法恢复的问题;5.0增加了新的流数据结构,使Redis拥有了全功能的轻量级消息队列能力;6.0发布了threaded-io、TLS、ACL等多项企业级特性,大大提升了Redis的性能和安全性。国内开发者与Redis社区建设得益于国内开发者,中国区已经成为Redis社区最大的贡献来源地之一。阿里云从Redis4.0开始就深度参与Redis开源社区,为社区贡献了很多能力。目前,阿里云在Redis社区有1名核心团队成员(核心维护者)和2名贡献者(核心贡献者),是除原作者和RedisLabs之外对Redis社区贡献最多的组织。我们见证了国内Redis用户的快速增长,阿里云与Redis社区的深度合作也逐渐吸引了更多国内开发者参与Redis建设。尤其是Redis核心团队成立后,社区维护者也像Redis一样变成了多线程(1->5),快速处理issue和PR大大提高了社区的活跃度。在这次7.0的releasenote中,也可以看到超过5位国内开发者贡献了核心特性,并且贡献了将近一半的commits。这些变化也与我们在阿里云上的统计结果一致:Redis也是国内用户使用量最大的NoSQL数据库之一,并且一直在高速增长。越来越多的泛互联网乃至传统行业也逐渐接受Redis来快速高效地构建业务应用服务。Redis虽然发展迅速,但国内大部分用户还无法享受到技术红利。目前Redis社区主流维护版本为6.0,5.0版本进入低维护阶段,而国内仍有大量2.8、3.0、4.0版本在使用。这是很矛盾的。一方面,新版本贡献了一些使用、性能、稳定性和抖动控制能力。另一方面,国内用户“能看,不能用”。排除6.0和7.0上的高级稳定性优化,比如4.0之前,如果没有lazyfree删除一个大key,会同步导致数据库引擎卡住,直接中断业务。再比如,Redis一直存在较大的安全问题,尤其是Lua,这些升级在新版本中也是“隐含”的。尽管阿里云仍在坚持将这些漏洞的修复带回低版本,但公网中仍然存在大量存在安全隐患的低版本实例。太多用户担心升级版本的兼容性。一方面,阿里云也在要求社区提供一些兼容性验证工具。另一方面,阿里云跟进版本的速度非常快,可以让用户在新版本发布后第一时间进行验证。.从Redis整体的升级情况和阿里云的大量客户来看,版本的前向兼容性非常好,可以放心升级。希望更多的国内用户深度参与社区建设。国外使用Redis的方式和国内有明显的区别。比如在国外更多的是用在缓存场景,而在国内用的最多的是内存数据库。随着社区的发展和路线图的制定,目前国内用户的呼声比较小。目前,国内的开发者在社区中非常活跃,但大多集中在bug修复和功能上。我们还是建议国内开发者和用户都可以深度参与。举个简单的例子,提出需求,澄清需求,证明需求的合理性,都是参与社区建设,让我们更好的了解我们国内的需求。沟通、跟进甚至深度参与开发、跟踪交付,这些社区工作的含金量无疑更高。在功能上,不仅是API层级的提升,还有可访问性、可观察性、一致性、一致性和安全性,目前都在等待社区的需求。虽然核心团队成员可以代表国内用户将一些需求写入路线图,但真实用户的声音会提供更强的支持。Redis使用场景的拓展与展望--Redis还能做什么?多模业务进入爆发期。Redis的开发离用户很近。它如此受欢迎主要是因为两个特点,即极高的性能和丰富易用。这些简单易用的数据结构可以大大降低业务开发的复杂度。我们可以看到,以Redislabs为代表的厂商都在大力丰富Redis的数据结构(模块),比如RedisSearch、Redis-Json、RedisGraph、RedisTimeSeries、RedisBloom等。同样,阿里云的内存数据库Tair也长期在开发各种增强的数据结构和模块。目前,我们在公有云Tair服务中提供的商用扩展数据结构比Redislabs提供的要多,部分模块功能更强。如果您有兴趣,请参阅文档(本文末尾的参考资料)。目前,大量云用户正在使用Tair增强的数据结构来构建代码,提高开发效率,甚至完成以前难以完成的任务。2022年是Redis扩容结构爆发的一年。行业已度过验收期,进入快速发展阶段。无论是Tair还是Redis,我们相信不断丰富的数据结构会让它们走得更远,从缓存向高性能计算型内存数据库演进,突破并解决更多的场景问题。一致性能力的培养磁盘一致性和副本一致性是使用数据库时绕不开的两个话题。一直以来,很多人只把Redis的应用场景确定为缓存(尤其是国外用户)。Redis从一开始就支持RDB和AOF两种持久化机制,AOF也提供了不同层次的持久化语义:比如appendfsync采用最高层次的always时,可以保证数据不会完全丢失,并且具有与传统数据库相同的强度。磁盘一致性。在多副本一致性方面,主要是指主备的一致性。原生Redis仍然使用异步复制。只要在本地执行数据修改操作,就会返回结果。与其他数据库相比,副本之间没有数据强一致性。语义。这也限制了Redis的使用场景,在对数据可靠性有极高要求的用户(如金融行业、传统行业)中并没有被完全接受。目前业界也在开发Redis的持久化能力。比较有代表性的有阿里云的Tair持久内存版,AWS的MemoryDB,还有一些业界开源的基于redis-likerocksdb的系统,比如Tair的容量存储版(以前叫混合存储)。Redis社区版Tair持久内存MemoryDB是基于rocksdb开源类Redis系统。可以配置磁盘一致性。Optane是完全持久的。云盘是完全持久化的。没有,有些可以配置。%略低,90%[1]左右低,15-25%[3]左右低,大写后停止服务容易卡顿。副本一致性(主备)无强一致性:半同步强一致性:未开启物理复制副本一致性后写入性能-低,约70%[2]低,约15-25%[4]-表1:社区Redis与其他商业和开源产品的磁盘一致性和副本一致性对比注1:与开源Redis社区版对比注2:与开源Redis基于内存的使用成本对比容量需求,成本,而数据的可靠性也在不断提升,这些也逐渐成为衡量Redis企业级能力的重要指标。各大厂商和开源产品也提出了很多解决方案来构建这些能力。下面介绍一些典型的产品和解决方案。AWSMemoryDBAWSMemoryDB的思路是基于类似于Aurora的共享存储概念,将日志存储在远程共享存储中,同时在内存中仍然保留了Redis原有的结构。这样,提高了数据的持久化一致性,同时也保证了数据读取的延迟和吞吐量;缺点是因为日志存储在远端,写入性能严重下降(只有ElastiCache,Redis社区版)15%~25%,数据来自AWS官方测评,参考参考本文结束)。在主从一致性方面,由于直接采用了日志的物理副本,因此主从一致性近似接近于磁盘一致性。值得一提的是,因为是在远端完成的,所以也避免了原来AOF重写的压缩(compaction)带来的开销,是一个非常彻底的云原生解决方案。阿里云自研内存数据库Tair在持久化方面另辟蹊径,引入持久化内存新介质,解决成本、大容量、持久化等问题。该方案带来的挑战是持久化内存存储结构设计相对复杂,需要控制性能退化和保证兼容性。Tair持久内存很好的解决了这些问题。与MemoryDB相比,成本更低,在读取性能基本相同的情况下,写入速度更快(见文末参考)。更重要的是,它基本原样兼容Redis。API,大大降低了用户的切换成本。而且,Tair持久内存类型还支持半同步和强写一致性。MemoryDB和Tair持久内存都真正满足了内存数据库的数据容错要求。其他开源产品的开发国内也有一些原创优秀的开源产品(Redis-Like系统),大部分都是基于LSM存储结构的,比如rocksdb。它们的优点主要是磁盘介质比内存便宜,但是也有很多缺点:运维复杂度高,直接映射到运维成本,KV不能原生支持Redis数据结构,Redis强类型变成弱类型等等在。目前这类系统在一致性和容错性方面还有很大的提升空间。在用户体验上,由于很多用户在业务的同步链路上仍然使用类Redis系统,对于LSMKV引擎抖动对延迟和整体吞吐量的影响直接体现在用户的物理体验上,所以它很难将其作为通用产品使用,而这些痛点在Tair容量存储类型(过去称为混合存储版本)中也存在,这也是一种需求。存储和兼容性方面长期优化的方向。综上所述,容量版可以很好的解决用户的使用成本问题,但只有更好地解决磁盘一致性问题和副本一致性问题,才能将类Redis系统的使用场景扩展到企业级。这也是目前云厂商竞争激烈的企业级产品的主流赛道,技术门槛也很高。写在最后Redislabs在2021年8月正式更名为Redis,可以看到社区版Redis的首页也进行了重构改版。Redis本身的商业化进展非常快,比如在首页“搭载”RedisStack;又比如在github上把常用的SDK都买下来后,开始增加一些Redislabs的商业开源支持等,最终Redis也可能像MongoDB、ElasticSearch一样完全商业化。但目前社区仍然非常开放和活跃。Redis8.0的特性计划已经启动。一方面,如前所述,我们建议国内开发者参与更深入的社区讨论,让社区更贴近国内的使用习惯。国内企业的情况很现实;另一方面,我们可以通过社区参与来提高我们的人才竞争力,去掉持久化系统,分布式架构,高吞吐低延迟核心引擎,多模式服务和脚本引擎,安全和审计需要持续的投入。如果国内有10-20位Redis领域顶尖的内存数据库专家,那么Redis即使商业化闭源,对国内用户的影响也很小。最后,欢迎大家使用Redis7.0,希望我们能在Redis等内存数据库技术上走得更远!参考资料:[1]Redis7.0MultiPartAOF设计与实现:https://img.ydisp.cn/news/20220629/jfsshe4k4g4MemoryDB与AmazonElastiCache的对比:https://aws.amazon.com/cn/blogs/china/comparison-of-amazon-memorydb-and-amazon-elasticache/?nc1=b_nrp[3]Tair扩展数据结构概述:https://help.aliyun.com/document_detail/146579.html[4]TairPersistent内存性能白皮书:https://help.aliyun.com/document_detail/185189.html
