Tendis(Redis)冷热混合存储怎么解决缓存击穿、雪崩、一致性3大难题

news/2024/11/29 1:46:29/

导语
缓存由于高并发和高性能的特性,经常被用于提高数据库的性能。但是业务往往需要花费大量精力来维护缓存和数据库的一致性。由IEG技术运营部/存储与计算资源中心 & 腾讯云数据库团队联合打造的 TendisX 冷热混合存储, 使用 Redis 作为缓存, Tendisplus 作为后端持久化数据库,并且自动将热数据加载到缓存,冷数据从缓存侧淘汰。业务侧使用完全透明,无需考虑缓存不一致的问题,从而更方便业务开发。

本文首先介绍由 IEG 技术运营部团队 & 腾讯云数据库团队开发的TendisX 冷热混合存储方案的整体架构,然后分析常用的解决缓存和数据库一致的方案存在的一些问题,最后从缓存一致性、击穿、雪崩、穿透、故障恢复、性能、业务接入复杂度等方面对这几个方案进行对比。

背景

在数据高并发读写场景, 数据库大多情况无法满足业务要求。 Redis 由于数据结构简单,读取速度快, 常常作为后端数据库的缓存使用。但是在使用缓存的时候,业务需要考虑: 1)是先写缓存还是先写数据库? 2)写请求是否更新缓存?等等问题。

TendisX 冷热混合存储方案

TendisX 是 IEG 技术运营部自研,主要解决 Redis 内存占用高和缓存不一致问题的 NoSQL 存储系统。
TendisX 冷热混合存储架构核心组件由 Proxy 、缓存Redis、存储Tendisplus组成,其中每个组件的功能介绍如下:

Proxy组件:负责对客户端请求进行路由分发,将不同的Key的命令分发到正确的分片,同时Proxy还负责了部分监控数据的采集,以及高危命令在线禁用等功能。

缓存Redis:缓存Redis组件基于 Redis 4.0 进行开发。Redis 具有以下功能:缓存全量的 Key;仅淘汰冷 Key 的 Value; 自动从 Tendisplus 恢复数据; Redis 限速。

存储Tendisplus:Tendisplus 是腾讯基于 RocksDB 自研的 兼容 Redis 协议的KV存储引擎,该引擎已经在腾讯集团内部运营多年,性能和稳定性得到了充分的验证。在混合存储系统中主要负责全量数据的存储和读取,以及数据备份,增量日志备份等功能。
在这里插入图片描述

缓存与数据库一致性的常规解决方案

在使用缓存的过程中往往会由于不正确的使用方式,导致缓存和后端数据库数据不一致,本章将介绍缓存的常见使用方式以及业界的解决缓存和数据库不一致的方案。

缓存使用方式

缓存作为一种广泛使用的技术, 常见的主要有以下三种使用模式: Cache Aside Pattern, Cache Through Pattern 和 Cache Back Pattern(具体介绍可以参考这篇文章Things You Should Know About Database Caching)。Cache Aside Pattern 是最常用的模式,Facebook 在 Scaling MemCache at Facebook 论文中也使用这种缓存模式。Cache Aside Pattern 采用先写数据库,再删除缓存,然而在某些情况也可能导致缓存和数据库的不一致。

在缓存+数据库的架构中,缓存和数据库的操作总共有以下几种顺序:

  1. 先更新缓存,再更新数据库
    业务方无法保证两个写操作都成功。当更新缓存成功,更新数据库失败时,数据库中就是旧数据。
  2. 先更新数据库,再更新缓存
    在多线程并发时,会出现不一致行为。假设请求 A 先操作数据库,请求 B 后操作数据库,但是可能存在请求 B 先写缓存,请求 A 后写缓存的情况,从而导致数据库与缓存之间的数据不一致。
  3. 先写数据库,再删除缓存
    业务要保证写数据库和删除缓存是一个原子操作,否则写数据成功,删除缓存失败就会出现数据不一致的问题。
  4. 先删缓存, 再写数据库
    先删除缓存,再写数据库前,可能另外一个读请求, 在缓存未命中时, 从数据库获取到旧值,将其放到缓存。 这时缓存中是旧值,数据库是新值。

通过上面分析可以得出,业务方无论是先写缓存还是先写数据库,最终都有可能出现缓存和数据库的不一致。那到底如何才能使缓存和数据库达到一致的状态。针对这个问题, 业界通常使用下面两种解决方案: 1)采用延时双删策略 2)异步更新缓存策略 。

采用延时双删策略

延时双删除策略会在写库前后删除缓存中数据,并且给缓存数据设置合理的过期时间, 从而可以保证最终一致性。写流程具体如下:

  1. 先删除缓存,再写数据库
  2. 休眠一段时间(比如500毫秒)
  3. 再次删除缓存

在这里插入图片描述
为什么会休眠一段时间,这里主要是防止: 在写请求删除缓存但还未成功写入数据库后,读请求可能将旧值加载到缓存。
读流程:先读缓存,当缓存未命中,再从数据库中读取,然后再写入缓存。
延时双删策略虽然解决了上述讨论的缓存和数据库不一致的问题,但是以下问题:

  1. 休眠一段时间可能会对性能造成影响;
  2. 在第二次删除缓存失败后,会导致数据不一致,需要业务方实现重试删除机制。

异步更新缓存策略(基于订阅binlog的同步机制)

异步更新缓存策略通常会使用一个异步同步组件(比如 canal 或者我司的 MySync), 通过解析从库的 binlog 获取数据,并通过消息队列将其串行化写入到缓存。
在这里插入图片描述
写流程:

  1. 先删除缓存,再写数据库
  2. 额外组件通过解析从库 binlog, 将写操作发送到消息队列
  3. 缓存从消息队列中消费,更新缓存

读流程:

  1. 先从缓存读取
  2. 如果缓存未命中, 从数据库读取, 将数据发送到消息队列。
  3. 缓存从消息队列消费,更新缓存。

异步更新缓存策略通过消息队列的方式将并行化的操作串行化,从而解决了并发问题。但是也引入一些其他问题,比如缓存相对主库落后延迟较大。

TendisX 混合存储方案

TendisX 中, 业务仅仅可以访问 Redis, 所有的数据恢复工作对业务不可见。因此业务可以简单的将其当做一个Redis 服务来用,而不用考虑各种缓存的问题。

Redis 与社区版不同的地方:

  1. **引入版本号 每次数据更新操作都会将 version++, 每个 Key 都会保存对应的 Version, 从而简单实现 缓存层和存储层复制幂等。
  2. Redis 中缓存全量的 Key 触发淘汰时,仅淘汰其对应的 Value。
  3. Redis 限速 为了避免后端数据库(Tendisplus) 落后缓存太多。当缓存中有大量的未持久化到Tendisplus 的数据时,阻塞用户写。
  4. 增量 RDB 在 slave 断线重连后, master 仅将断线内新增的数据发给 slave

写请求流程如下:

  1. 写入 Redis 缓存,成功后返回。
  2. 后台异步回刷,将数据持久化到后端 Tendisplus。

在这里插入图片描述
读请求的处理流程:

  1. 从 Redis 读取数据 。
  2. 如果命中,那么就将数据返回给应用程序。
  3. 如果未命中,阻塞当前客户端, Redis 负责将 Key 从 Tendisplus 中恢复,然后返回给用户。

在这里插入图片描述

方案对比

下面主要从缓存问题、主备切换场景、性能以及业务接入复杂度方面,对比 TendisX 冷热存储和延时双删策略、异步刷新策略。

缓存问题

TendisX 在使用过程中不会出现缓存穿透、缓存击穿、缓存雪崩和缓存不一致等问题。但是延时双删策略和异步刷新策略要看业务方如何处理,解决这些问题。

缓存穿透

缓存穿透是指查询数据库不存在的数据。当查询缓存和数据库都没有的 Key 时,由于 TendisX 中 redis 缓存用户的所有 key, 因此可以直接通过 redis 判断该 key 是否存在,不会有缓存穿透的问题。

缓存击穿

如果某些 Key 可能会在某些时间点被超高并发地访问,则它是一种非常“热点”的数据。缓存击穿是指大量的请求同时查询一个失效的热点数据,导致请求全部转发到数据库。
当某个热点的 Key 失效时,当下次具有大量该 Key 的请求时,TendisX 执行流程如下:

  1. 阻塞当前 Key 的请求
  2. 从后端存储恢复数据
  3. 在Key 对应的Value 还未恢复的过程中, 如果有其他请求继续获取该 Key, 同样阻塞该请求
  4. 当key 从后端恢复后,依次唤醒该 Key 对应阻塞的请求。

缓存雪崩

缓存雪崩是指某一时刻发生大规模的缓存失效的情况,比如缓存故障或者缓存采用相同的过期时间,缓存在某一时刻同时失效, 请求全部转发给数据库。
TendisX 可以利用 Redis 集群模式实现高可用,即使缓存故障,也可以及时通过备缓存恢复服务。另外 TendisX 的用户请求统一由缓存服务,请求不会转发给后端数据库。

缓存一致性

延时双删策略

  1. 延时双删策略通过休眠一段时间,再次删除缓存来解决缓存不一致的问题。但是由于每次写都要睡眠一段时间, 写操作耗时较长,从而大大降低系统的吞吐量。
    在第二次删除缓存失败后,缓存和数据库不一致。为了解决这个问题需要业务在失败后提供重试删除机制,大大增加了业务开发成本。

异步更新缓存策略
通过解析从库的 binlog ,再通过消息队列串行化发给缓存, 缓存较主库延迟较大。比如大概率会出现业务写入主库更新数据,缓存还未更新,业务从缓存中得到旧值。

TendisX 混合存储
对于并发读写,经常会出现缓存不一致的场景:
请求 A 进行写操作
请求 B 进行读操作
redis 是单线程串行化执行用户的请求, 当写操作先执行。

如果需要从 Tendisplus 中恢复数据,则请求 A 和 B 都阻塞。当数据恢复后,再唤醒阻塞的请求 A 和 B, 缓存和后端 Tendisplus 最终是一致的。
如果不需要从 Tendisplus 中恢复数据,则请求 A 和 B 肯定是顺序执行的,不会出现不一致的行为。

主备故障场景分析

当 TendisX 中 redis master 故障时, 后端的 Tendisplus 可以切到对应的 redis slave。主备之间通过异步复制,可能会造成部分数据丢失。 TendisX 在 redis 主备和 redis 和 Tendisplus 同步的时候提供了限速,也就是说 slave 最多比 master 慢 2秒的数据(业务方在最差情况下丢失的数据)。
当 TendisX 中后端 Tendisplus 主故障时, Tendisplus 备可以切换到对应的 redis master,从 redis master 继续同步数据,数据不会丢失。

对于延时双删策略和异步刷新策略
如果缓存故障,并且假设缓存使用 redis, 也可以使用 redis 自动故障切换。但是由于是先写数据库,不会有数据丢失。
如果数据库故障,如果数据库主备间使用异步复制,也会有一定的数据丢失。

数据可容忍的丢失程度。

性能分析

延时双删策略和异步刷新策略的劣势:

  • 延时双删策略,第二次删除前要等待一段时间,大大降低了系统的吞吐量(虽然可以通过一些异步删除的方法来改善,增加业务方的使用难度)。
  • 延时双删策略和异步刷新策略每次更新数据库前,都要删除缓存。下次读请求都要从后端加载数据,大大影响了性能。
  • 延时双删策略和异步刷新策略每次都会写到后端数据库,写入流程耗时较长。

TendisX的一些性能优势:

  • TendisX 写入仅仅是一次内存操作,响应时间短。
  • TendisX 中 redis 缓存所有 key, 对于一些需要全量 Key的操作不用扫描后端数据库,大大缩短了时间。
  • TendisX 每次直接写入到缓存,后续的请求都可以通过缓存提供,而不是从后端再次读取。

业务接入复杂度

延时双删策略需要业务同时操作缓存和数据库,同时业务方也要保证第二次删除缓存失败后的重试,对业务来说使用比较麻烦,不友好。
业务方可以将 TendisX 当做一个 Redis 缓存来用,不用担心各种缓存问题。

总结对比

下面通过一个表来直观的对比 TendisX 冷热混合存储和另外两种策略:
在这里插入图片描述


http://www.ppmy.cn/news/615739.html

相关文章

“魂系”游戏的魅力,不止在于受苦——浅谈黑暗之魂的设计特色

引言如果要选出“游戏中最令人印象深刻的词”的话,“YOU DIED”绝对会在许多玩家心目中占据一席之地。“YOU DIED”是黑暗之魂系列里,玩家角色每次死亡时,屏幕上会出现的告示。每个玩过魂系列的人,一定见到过这个告示许多次。黑暗…

Nginx的Location和Rewrite

目录 Rewrite简介 1.0 Rewrite实际场景 1.1 Rewrite跳转场景 1.2 Rewrite跳转实现 1.3 Nginx正则表达式 1.4 Rewrite命令&&语法格式 1.5 flag标记说明 2 Location分类 2.1 Location优先级 3 Rewrite&&Location比较 4 场景跳转实验 4.1 基于域名的跳转 …

FreeRTOS_列表和列表项

目录 1. 什么是列表和列表项? 1.1 列表 1.2 列表项 1.3 迷你列表项 2. 列表和列表项初始化 2.1 列表初始化 2.2 列表项初始化 3. 列表项插入 3.1 列表项插入函数分析 3.2 列表项插入过程图示 3.2.1 插入值为 40 的列表项 3.2.2 插入值为 60 的列表项 3…

计算机主机外设接口,2002.12计算机组成原理§1主机与外设的连接.ppt

2002.12计算机组成原理1主机与外设的连接 第十章 现代计算机系统中外部设备的种类繁多,各类外部设备不仅结构组成和工作原理不同,而且与主机的连接方式也是复杂多变的。因此,计算机的输入/输出子系统成为整个计算机系统中最具有多样性和复杂性…

台式计算机音响外设插入,台式机提示外设没有插上

台式机提示外设没有插上 导读:小编根据大家的需要整理了一份关于《台式机提示外设没有插上》的内容,具体内容:电脑没有声音提示“外设似乎没有插上”怎么办,很多人在重装系统后,特别是win系统重装后,我们再…

CPU与外设传输方式

如果外设想要工作,那么他就必须去找CPU请求服务,只有得到CPU的批准,这样才可以为其分配计算机资源,让其完成任务。 随着进步,CPU与外设之间产生了4种访问方式。 1.轮询方式。 每隔一段时间CPU就会在一定的周期时间内…

CPU与外设之间交换方式

什么是输入输出 输入输出系统是计算机系统中的主机与外部进行通信的系统。它由外围设备和输入输出控制系统两部分组成,是计算机系统的重要组成部分。外围设备包括输入设备、输出设备和磁盘存储器、磁带存储器、光盘存储器等。从某种意义上也可以把磁盘、磁带和光盘…

STM32基础和常见外设

STM32 开发环境 安装MDK软件在桌面创建一个用于专门保存是stm32 的文件夹安装芯片包打开软件新建工程&#xff08;Project&#xff09;保存到文件夹将启动文件添加到文件夹 点亮LED灯 配置使能APB2的GPIOC时钟 *(unsigned int *)0x4002 1010 | 0x01 << 4 //起始地址偏…