From f48a393882eeadf9d53e0c6928dde74fe5aaee67 Mon Sep 17 00:00:00 2001 From: dongyuanxin Date: Fri, 12 Jul 2019 13:10:05 +0800 Subject: [PATCH] fix: markdown lint --- .vuepress/config/sidebar.js | 1 + ...56\351\242\230\347\240\224\347\251\266.md" | 101 +++++++----------- 2 files changed, 40 insertions(+), 62 deletions(-) diff --git a/.vuepress/config/sidebar.js b/.vuepress/config/sidebar.js index 37632aa25..0087c0aba 100644 --- a/.vuepress/config/sidebar.js +++ b/.vuepress/config/sidebar.js @@ -131,6 +131,7 @@ const design = [ const weekly = [ '', + '2019/04-redis热key等问题研究', '2019/03-心谭-无声半年', '2019/02-心谭-如何缩小学习反馈周期', '2019/01-心谭-第一期', diff --git "a/\346\257\217\345\221\250\345\210\206\344\272\253/2019/04-redis\347\203\255key\347\255\211\351\227\256\351\242\230\347\240\224\347\251\266.md" "b/\346\257\217\345\221\250\345\210\206\344\272\253/2019/04-redis\347\203\255key\347\255\211\351\227\256\351\242\230\347\240\224\347\251\266.md" index c833ce63f..3cc2da133 100644 --- "a/\346\257\217\345\221\250\345\210\206\344\272\253/2019/04-redis\347\203\255key\347\255\211\351\227\256\351\242\230\347\240\224\347\251\266.md" +++ "b/\346\257\217\345\221\250\345\210\206\344\272\253/2019/04-redis\347\203\255key\347\255\211\351\227\256\351\242\230\347\240\224\347\251\266.md" @@ -1,19 +1,19 @@ --- title: "redis热key,缓存穿透,击穿,集群等问题研究" -date: "2019-07-012" +date: "2019-07-12" permalink: "2019-07-12-redis-cache-question" --- -Redis主要用途有2个 +> 本篇由来自 **字节跳动** 的 [Hongkai](https://github.com/HuangHongkai) 分享。 -- 数据缓存,减轻db的压力 -- 数据同步,在分布式系统中各个实例的信息同步 - -redis的QPS量通常相当的大,动辄百万QPS,一般企业都需要很庞大的redis集群资源。由于redis的使用相当频繁,经常会出现各种问题。根据目前积累的线上经验,redis出现问题第一步就是要想到:**redis是单进程单线程实例** 理解这一点通常能解决很多问题。 +Redis 主要用途有 2 个 -下面介绍一些redis的一些理论知识。 +- 数据缓存,减轻 db 的压力 +- 数据同步,在分布式系统中各个实例的信息同步 +redis 的 QPS 量通常相当的大,动辄百万 QPS,一般企业都需要很庞大的 redis 集群资源。由于 redis 的使用相当频繁,经常会出现各种问题。根据目前积累的线上经验,redis 出现问题第一步就是要想到:**redis 是单进程单线程实例** 理解这一点通常能解决很多问题。 +下面介绍一些 redis 的一些理论知识。 ## 主从模式 @@ -21,15 +21,11 @@ redis的QPS量通常相当的大,动辄百万QPS,一般企业都需要很庞 ### 概念 -在redis或mysql等数据库中,数据库分为两类,一类是主数据库(master),另一类是从数据库(slave)。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。 - - +在 redis 或 mysql 等数据库中,数据库分为两类,一类是主数据库(master),另一类是从数据库(slave)。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。 ### 复制原理 -当从数据库启动时,会向主数据库发送sync命令,主数据库接收到sync后开始在后台保存快照rdb,在保存快照期间受到的命名缓存起来,当快照完成时,主数据库会将快照和缓存的命令一块发送给从。复制初始化结束。之后,主每接收到1个命令就同步发送给从。 当出现断开重连后,2.8之后的版本会将断线期间的命令传给从数据库。 - - +当从数据库启动时,会向主数据库发送 sync 命令,主数据库接收到 sync 后开始在后台保存快照 rdb,在保存快照期间受到的命名缓存起来,当快照完成时,主数据库会将快照和缓存的命令一块发送给从。复制初始化结束。之后,主每接收到 1 个命令就同步发送给从。 当出现断开重连后,2.8 之后的版本会将断线期间的命令传给从数据库。 ### 优点: @@ -37,58 +33,48 @@ redis的QPS量通常相当的大,动辄百万QPS,一般企业都需要很庞 - 提升系统容灾能力 - - ### 缺点: -- 承载的容量非常有限,假设服务器的内存都是40G,有10台服务器,意味着只能容纳40G的数据。 -- 刚写入的数据可能获取不到(因为数据还没有更新到其他服务器上) - - +- 承载的容量非常有限,假设服务器的内存都是 40G,有 10 台服务器,意味着只能容纳 40G 的数据。 +- 刚写入的数据可能获取不到(因为数据还没有更新到其他服务器上) ## 哨兵 -在主从模式下,当主服务出现异常会导致整体redis不可写。开发者需要手动将一个从数据库升级为主数据库保证服务正常运行。该过程难以自动后,为此在redis2.8后提供了哨兵来实现故障恢复功能。 +在主从模式下,当主服务出现异常会导致整体 redis 不可写。开发者需要手动将一个从数据库升级为主数据库保证服务正常运行。该过程难以自动后,为此在 redis2.8 后提供了哨兵来实现故障恢复功能。 -哨兵就是redis的监控系统,包括2个功能 +哨兵就是 redis 的监控系统,包括 2 个功能 -- 监控主数据库和从数据库是否正常运行。 -- 主数据库出现故障时自动将从数据库转换为主数据库。 +- 监控主数据库和从数据库是否正常运行。 +- 主数据库出现故障时自动将从数据库转换为主数据库。 ### 主从切换过程 -- slave leader升级为master -- 其他slave修改为新master的slave -- 客户端修改连接 -- 老的master如果重启成功,变为新master的slave - - +- slave leader 升级为 master +- 其他 slave 修改为新 master 的 slave +- 客户端修改连接 +- 老的 master 如果重启成功,变为新 master 的 slave ### 集群 -使用哨兵,redis每个实例也是全量存储,每个redis存储的内容都是完整的数据,浪费内存且有木桶效应。为了最大化利用内存,可以采用集群,即每台机器存储不同的内容。 - -简单来讲:通过不断的扩容和增加运行redis实例的机器数量,使得redis能撑得住更大的访问量 - +使用哨兵,redis 每个实例也是全量存储,每个 redis 存储的内容都是完整的数据,浪费内存且有木桶效应。为了最大化利用内存,可以采用集群,即每台机器存储不同的内容。 +简单来讲:通过不断的扩容和增加运行 redis 实例的机器数量,使得 redis 能撑得住更大的访问量 ### 原理 -redis cluster中有一个16384(2^4 * 2^10)长度的槽的概念。通过哈希算法再加上取模运算可以将一个值固定地映射到某个区间,区间由连续的slot组成。 +redis cluster 中有一个 16384(2^4 \* 2^10)长度的槽的概念。通过哈希算法再加上取模运算可以将一个值固定地映射到某个区间,区间由连续的 slot 组成。 -redis cluster采用虚拟槽分区,所有的键根据哈希函数(CRC16[key]&16383)映射到0-16383槽内,共16384个槽位,每个节点维护部分槽及槽所映射的键值数据,可以为节点设置权重,权重高的节点维护的槽的数量比较多。 +redis cluster 采用虚拟槽分区,所有的键根据哈希函数(CRC16[key]&16383)映射到 0-16383 槽内,共 16384 个槽位,每个节点维护部分槽及槽所映射的键值数据,可以为节点设置权重,权重高的节点维护的槽的数量比较多。 哈希函数: Hash()=CRC16[key]&16383 按位与 -redis用虚拟槽分区原因:解耦数据与节点关系,节点自身维护槽映射关系,分布式存储 - - +redis 用虚拟槽分区原因:解耦数据与节点关系,节点自身维护槽映射关系,分布式存储 ### 集群模式 - 客户端模式 -在客户端做redis负载均衡,通过服务发现注册redis节点,实现redis节点的动态改变(增删或者节点扩容) +在客户端做 redis 负载均衡,通过服务发现注册 redis 节点,实现 redis 节点的动态改变(增删或者节点扩容) ![img](https://i.loli.net/2019/07/12/5d27764947bf559054.png) @@ -96,22 +82,20 @@ redis用虚拟槽分区原因:解耦数据与节点关系,节点自身维护 - 数据分散,使得整体容量得到提升 - 当一个节点不可用不会导致整体服务不可用 -- 性能高,客户端直接连接redis,不通过代理 +- 性能高,客户端直接连接 redis,不通过代理 - 扩容方便 -目前企业使用的redis集群基本都是客户端模式,这样可以减轻服务端的压力。 +目前企业使用的 redis 集群基本都是客户端模式,这样可以减轻服务端的压力。 - 代理模式 -客户端不是直接连接redis,而是连接代理,这样子客户端的开发就变得简单很多了。。同时服务端也可以控制redis的连接数。 +客户端不是直接连接 redis,而是连接代理,这样子客户端的开发就变得简单很多了。。同时服务端也可以控制 redis 的连接数。 ![img](https://i.loli.net/2019/07/12/5d27764e1a87934952.png) ### 分析 -集群模式的解决了容量的问题,但是带来了很多的问题,例如redis的热key问题,单点高并发会导致redis负载及其不均衡,进而服务可用性极低。 - - +集群模式的解决了容量的问题,但是带来了很多的问题,例如 redis 的热 key 问题,单点高并发会导致 redis 负载及其不均衡,进而服务可用性极低。 ## 穿透 @@ -123,44 +107,37 @@ redis用虚拟槽分区原因:解耦数据与节点关系,节点自身维护 频繁查询一个不存在的数据,由于缓存不命中,每次都要查询持久层。从而失去缓存的意义。 -如果恶意用户知道我们redis key的构造规则,每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查询,这样缓存就失去了意义。如果在高并发下数据库可能挂掉。这就是**缓存击穿**。 - - +如果恶意用户知道我们 redis key 的构造规则,每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查询,这样缓存就失去了意义。如果在高并发下数据库可能挂掉。这就是**缓存击穿**。 ## 雪崩 -redis缓存大量失效的时候,引发大量查询数据库。如果有的数据只放在redis上(例如用来同步多个服务实例信息之间的共享数据),redis缓存失效会导致服务出现异常,这比查数据库更加严重 - -引起这个问题的原因主要是redis单点被打垮,也就是热key问题。 - +redis 缓存大量失效的时候,引发大量查询数据库。如果有的数据只放在 redis 上(例如用来同步多个服务实例信息之间的共享数据),redis 缓存失效会导致服务出现异常,这比查数据库更加严重 +引起这个问题的原因主要是 redis 单点被打垮,也就是热 key 问题。 ## 击穿 - 缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力 +缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力 解决方案: - 设置频繁访问的数据过期(让缓存持续命中) -- 加分布式锁(如果缓存不存在,只让一个进程去读db,有点类似于单例模式的实现,下面是一个从网上找的小demo) +- 加分布式锁(如果缓存不存在,只让一个进程去读 db,有点类似于单例模式的实现,下面是一个从网上找的小 demo) ![img](https://i.loli.net/2019/07/12/5d277650ad21c42141.png) - - -### 热key +### 热 key 在集群模式下经常会遇到这个问题,业界依然没有好的解决方案(参见微博只要热点事件就垮了) -热key:某个key访问非常的频繁,**redis集群负载不均衡,导致单点延迟增加,从而导致单点redis上的缓存不可用。** +热 key:某个 key 访问非常的频繁,**redis 集群负载不均衡,导致单点延迟增加,从而导致单点 redis 上的缓存不可用。** -这个问题相当的难以解决,微博在出现热点事件后服务不可用,很大原因是热key问题,导致单点redis被打垮了, 增加db访问量,进而系统雪崩。 +这个问题相当的难以解决,微博在出现热点事件后服务不可用,很大原因是热 key 问题,导致单点 redis 被打垮了, 增加 db 访问量,进而系统雪崩。 -因为**redis是单进程单线程** ,redis的处理线程忙起来,会导致redis没空accept来自client的tcp请求,进而出现连接超时的错误,缓存未命中。 +因为**redis 是单进程单线程** ,redis 的处理线程忙起来,会导致 redis 没空 accept 来自 client 的 tcp 请求,进而出现连接超时的错误,缓存未命中。 ### 解决方案 -没有具体的解决方案,需要根据业务来制定。思路**将key打散**,就是将redis访问某个热key,转化为访问多个key,减轻单点压力 +没有具体的解决方案,需要根据业务来制定。思路**将 key 打散**,就是将 redis 访问某个热 key,转化为访问多个 key,减轻单点压力 但并不是所有的业务都能使用该解决方案。 -