Tair 对 Redis 引擎架构之争的看法

背景

2022 年 6 月 8 日,Redis Inc. 的官方博客发布了一篇名为《13 年后,Redis 是否需要一个新架构?》[1]的文章,这篇文章由 Redis 的联合创始人兼 CTO Yiftach Shoolman、首席架构师 Yossi Gottlieb 以及性能工程师 Filipe Oliveira 联合署名,被业界认为是 Redis 官方针对 Dragonfly[2] “碰瓷式”营销的回应。

Dragonfly 是一款兼容 Redis/Memcached 协议的内存存储系统,从 Dragonfly 官方发布的基准测试结果来说,声称自己比 Redis 快了 25 倍,单个存储节点可以处理数百万的请求。官方给的性能基准测试结果如下:

(当然 Dragonfly 以多线程对比 Redis 单线程,这个评测的公平性有待于商榷)

截止 2022 年 8 月 10 日,Dragonfly 在 github 上已经有了 9.3 K 的 star 和 83 个 fork 的分支。虽然以前就有诸如 KeyDB[3] 或者 Skytable [4]这样的 Redis 挑战者,但是从来没有一款产品得到 Redis 官方的正式回应。此次官方的正式撰文回应,在外界看来至少也说明 Dragonfly 相较于之前的挑战者有了更大的影响力。

Redis 官方博客这篇文章对 Dragonfly 和 Redis 重新做了性能基准测试,以 40 分片 Redis 集群的方式重新压测对比 Dragonfly 单节点的性能(没说明 Dragonfly 单节点使用了多少线程),得出了 Redis 在同等资源占用下,吞吐量比 Dragonfly 要高出 18% 至 40%的结论:

​(当然这个测试也没说 Redis 集群下功能是受限的,多 key 操作命令有额外的限制)

文章最后给出了 Redis 当下架构设计的几个原则/目标:

  • 在每个 VM 上运行多个 Redis 实例

  • 将每个 Redis 进程限制在合理的(内存)大小

  • 水平扩展至关重要

尤其是第三点文章用了很大篇幅来说明:比如单线程多分片的架构设计更加弹性、会有更小的爆炸半径、纵向扩展导致实例容量翻倍、更贴近 NUMA 架构等等,其他涉及 Redis Inc 商业版本因 AWS 的硬件限制以及自身数据中心限制带来的设计影响在这里不陈述了。

Tair 引擎架构的发展

传统 Redis 单线程模式和层出不穷的多线程挑战者之间擦出的火花愈演愈烈,作为耕耘了这个领域近 12 年的 Tair 怎么看待这个架构之争呢?Tair 自研引擎使用的架构也是多线程,这么看来 Tair 认为多线程才是唯一正确的设计吗?当然没这么简单,Tair 做多线程的根因不仅仅是因为单节点的性能问题,更不是单纯为了单节点的跑分去设计实现多线程引擎架构的。去年发布的这篇文章中提到了我们的大客户业务场景下遇到的诸多问题,这里再次引用下文中的部分场景以便于后续的讨论:

  • 某用户打满了 Redis 的服务,主线程 CPU 使用率 100% 后业务开始卡顿。为了解决问题,用户紧急在控制台进行扩容。然而 Redis 主线程过于繁忙,新的主备关系很难建立,建立后数据同步进度特别慢。用户特别着急,但我们除了让用户降低流量外束手无策(限流对业务伤害太大,当下只是卡顿,限流会大面积不可用)。最后怎么解决的?说来惭愧,等用户流量降低后才升配成功的。

  • 某用户的访问存在间歇的峰值,主线程负载时不时飙高,导致管控采集服务监控的请求也时不时超时。最终造成了监控数据的曲线出现断点,引发了用户投诉。为什么超时?因为监控链路和数据链路都是主线程处理的。当前只是在社区版上把探活端口和逻辑移动到了另外的线程,监控和管控仍在主线程。(正在改造,但是还是遇到了很多困难。因为 Redis 单线程,所以数据结构都是线程不安全的。所以在别的线程获取信息要么加锁,要么主线程提前生成好。提前生成看起来挺好是吧?但是主线程执行一个慢查询的时候,也就不会执行生成的定时任务去生成这个信息了,拿到的也是旧的)。

  • 读写分离场景下,Redis 链式挂载了多个同步只读节点,从 Master 开始直到最后的只读节点,数据更新同步的一致性逐渐降低(链式逐个同步存在时差)。当 Master 遇到大流量打满 CPU 时,容易造成主从断开(堆积的同步请求太多或者心跳失败),然后触发链式同步断开后逐个节点全量同步。然而 CPU 是打满的,同步断开后更难建立了,最终难以恢复。为什么是链式同步不是星型同步?链式只挂载一个只读节点都会出问题还敢星型啊?我们能做什么?检测到这个情况后 Proxy 隔离数据不同步的从节点。但是!这是读写分离实例啊,流量大到了主从都断开了,隔离了更多的只读节点这是要让系统雪崩吗

  • Redis 作为缓存使用时,为了缓存一致性,数据都是有过期时间兜底的。如果一个节点长期以高 CPU 运行时,过期检查和清理的定时任务就得不到足够多的优先级去执行,累积的过期数据过多后达到内存上限就会淘汰。业务会发现明明存在很多过期数据,但是淘汰的却不一定是过期的数据。

  • Redis 的内存统计是进程级别的,没有分区域(数据区,元数据区、Client buf 等等),当遇到了一些网络延迟大或者客户端/服务端处理缓慢的情况时,会造成较多的 Client buf 占用。当内存统计达到设置的阈值后就开始淘汰用户数据了。那为什么不把统计分开?统计各个单独区域有这么难吗?技术上不难,但是这是个繁琐的工作,但凡漏掉一处就会引发大问题。Redis 怎么统计全局的?Redis 内存分配和释放在 malloc 和 free

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值