Redis 切片集群的数据倾斜分析
Redis 中如何应对数据倾斜
什么是数据倾斜
如果 Redis 中的部署,采用的是切片集群,数据是会按照一定的规则分散到不同的实例中保存,比如,使用 Redis Cluster
或 Codis
。
数据倾斜会有下面两种情况:
1、数据量倾斜:在某些情况下,实例上的数据分布不均衡,某个实例上的数据特别多。
2、数据访问倾斜:虽然每个集群实例上的数据量相差不大,但是某个实例上的数据是热点数据,被访问得非常频繁。
发生了数据倾斜,会造成那些数据量大的和访问高的实例节点,系统的负载升高,响应速度变慢。严重的情况造成内存资源耗尽,引起系统崩溃。
数据量倾斜
数据量倾斜,也就是实例上的数据分布不均衡,某个实例中的数据分布的特别多 。
数据量的倾斜,主要有下面三种情况:
1、bigkey导致倾斜;
2、Slot分配不均衡导致倾斜;
3、Hash Tag导致倾斜。
下面来一一的分析下
bigkey导致倾斜
什么是 bigkey
:我们将含有较大数据或含有大量成员、列表数的 Key 称之为大Key。
一个 STRING 类型的 Key,它的值为 5MB(数据过大)
一个 LIST 类型的 Key,它的列表数量为 20000 个(列表数量过多)
一个 ZSET 类型的 Key,它的成员数量为 10000 个(成员数量过多)
一个 HASH 格式的 Key,它的成员数量虽然只有 1000 个但这些成员的 value 总大小为 100MB(成员体积过大)
如果某个实例中保存了 bigkey
,那么就有可能导致集群的数据倾斜。
bigkey
存在问题
内存空间不均匀:如果采用切片集群的部署方案,容易造成某些实例节点的内存分配不均匀;
造成网络拥塞:读取 bigkey 意味着需要消耗更多的网络流量,可能会对 Redis 服务器造成影响;
过期删除:bigkey 不单读写慢,删除也慢,删除过期 bigkey 也比较耗时;
迁移困难:由于数据庞大,备份和还原也容易造成阻塞,操作失败;
如何避免
对于bigkey
可以从以下两个方面进行处理
1、合理优化数据结构
1、对较大的数据进行压缩处理;
2、拆分集合:将大的集合拆分成小集合(如以时间进行分片)或者单个的数据。
2、选择其他的技术来存储 bigkey
;
- 使用其他的存储形式,考虑使用 cdn 或者文档性数据库 MongoDB。
Slot分配不均衡导致倾斜
例如在 Redis Cluster
通过 Slot 来给数据分配实例
1、Redis Cluster
方案采用哈希槽来处理 KEY 在不同实例中的分布,一个切片集群共有 16384 个哈希槽,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中;
2、一个 KEY ,首先会根据 CRC16 算法计算一个16 bit的值;然后,再用这个 16bit 值对 16384 取模,得到 0~16383 范围内的模数,每个模数代表一个相应编号的哈希槽。
3、然后把哈希槽分配到所有的实例中,例如,如果集群中有N个实例,那么,每个实例上的槽个数为16384/N个。
如果 Slot 分配的不均衡,就会导致某几个实例中数据量偏大,进而导致数据倾斜的发生。
出现这种问题,我们就可以使用迁移命令把这些 Slot 迁移到其它实例上,即可。
Hash Tag导致倾斜
Hash Tag
用于 redis 集群中,其作用是将具有某一固定特征的数据存储到同一台实例上。其实现方式为在 key 中加个 {}
,例如 test{1}
。
使用 Hash Tag
后客户端在计算 key 的 crc16 时,只计算 {}
中数据。如果没使用 Hash Tag
,客户端会对整个 key 进行 crc16 计算。
数据key | 哈希计算 | 对应的Slot |
---|---|---|
user:info:{3231} | CRC16('3231') mod 16384 | 1024 |
user:info:{5328} | CRC16('5328') mod 16384 | 3210 |
user:order:{3231} | CRC16('3231') mod 16384 | 1024 |
user:order:{5328} | CRC16('5328') mod 16384 | 3210 |
这样通过 Hash Tag
就可以将某一固定特征数据存储到一台实例上,避免逐个查询集群中实例。
栗如:如果我们进行事务操作或者数据的范围查询,因为Redis Cluster
和 Codis 本身并不支持跨实例的事务操作和范围查询,当业务应用有这些需求时,就只能先把这些数据读取到业务层进行事务处理,或者是逐个查询每个实例,得到范围查询的结果。
Hash Tag
潜在的问题就是,可能存在大量数据被映射到同一个实例的情况出现,导致集群的数据倾斜,集群中的负载不均衡。
所有当我使用 Hash Tag
的时候就做好评估,我们的业务诉求如果不使用 Hash Tag
可以解决吗,如果不可避免的使用,我们需要评估好数据量,尽量避免数据倾斜的出现。
数据访问倾斜
虽然每个集群实例上的数据量相差不大,但是某个实例上的数据是热点数据,被访问得非常频繁,这就是数据访问倾斜。
数据量访问倾斜的罪魁祸首就是 Hot Key
切片集群中的 Key 最终会存储到集群中的一个固定的 Redis 实例中。某一个 Key 在一段时间内访问远高于其它的 Key,也就是该 Key 对应的 Redis 实例,会收到过大的流量请求,该实例容易出现过载和卡顿现象,甚至还会被打挂掉。
常见引发热点 Key 的情况:
1、新闻中的热点事件;
2、秒杀活动中的,性价比高的商品;
如何发现 Hot Key
- 1、提现预判;
根据业务经验进行提前预判;
- 2、在客户端进行收集;
通过在客户端增加命令的采集,来统计发现热点 Key;
- 3、使用 Redis 自带的命令排查;
使用monitor命令统计热点key(不推荐,高并发条件下会有造成redis 内存爆掉的隐患);
hotkeys参数,redis 4.0.3提供了redis-cli的热点key发现功能,执行redis-cli时加上–hotkeys选项即可。但是该参数在执行的时候,如果key比较多,执行起来比较慢。
- 4、在Proxy层做收集
如果集群架构引入了 proxy,可以在 proxy 中做统计
- 5、自己抓包评估
Redis客户端使用TCP协议与服务端进行交互,通信协议采用的是RESP。自己写程序监听端口,按照RESP协议规则解析数据,进行分析。缺点就是开发成本高,维护困难,有丢包可能性。
Hot Key 如何解决
知道了Hot Key
如何来应对呢
- 1、对 Key 进行分散处理;
举个栗子
有一个热 Key 名字为Hot-key-test
,可以将其分散为Hot-key-test1
,Hot-key-test2
...然后将这些 Key 分散到多个实例节点中,当客户端进行访问的时候,随机一个下标的 Key 进行访问,这样就能将流量分散到不同的实例中了,避免了一个缓存节点的过载。
一般来讲,可以通过添加后缀或者前缀,把一个 hotkey 的数量变成 redis 实例个数 N 的倍数 M,从而由访问一个redis key
变成访问N * M
个redis key。 N*M
个redis key
经过分片分布到不同的实例上,将访问量均摊到所有实例。
const M = N * 2
//生成随机数
random = GenRandom(0, M)
//构造备份新key
bakHotKey = hotKey + “_” + random
data = redis.GET(bakHotKey)
if data == NULL {
data = GetFromDB()
redis.SET(bakHotKey, expireTime + GenRandom(0,5))
}
- 2、使用本地缓存;
业务端还可以使用本地缓存,将这些热 key 记录在本地缓存,来减少对远程缓存的冲击。
这里,有个地方需要注意下,热点数据多副本方法只能针对只读的热点数据。如果热点数据是有读有写的话,就不适合采用多副本方法了,因为要保证多副本间的数据一致性,会带来额外的开销。
对于有读有写的热点数据,我们就要给实例本身增加资源了,例如使用配置更高的机器,来应对大量的访问压力。
总结
1、数据倾斜会有下面两种情况;
1、数据量倾斜:在某些情况下,实例上的数据分布不均衡,某个实例上的数据特别多。
2、数据访问倾斜:虽然每个集群实例上的数据量相差不大,但是某个实例上的数据是热点数据,被访问得非常频繁。
2、数据量的倾斜,主要有下面三种情况;
1、bigkey导致倾斜;
2、Slot分配不均衡导致倾斜;
3、Hash Tag导致倾斜。
3、数据访问倾斜,原因就是 Hot Key
造成的,出现Hot Key
,一般下面有下面两种方式去解决;
1、对 Key 进行分散处理;
2、使用本地缓存;
参考
【Redis核心技术与实战】https://time.geekbang.org/column/intro/100056701
【Redis设计与实现】https://book.douban.com/subject/25900156/
【Redis 的学习笔记】https://github.com/boilingfrog/Go-POINT/tree/master/redis
【Redis中的切片集群】https://boilingfrog.github.io/2022/02/20/redis中常见的集群部署方案/#切片集群
【Redis 切片集群的数据倾斜分析】https://boilingfrog.github.io/2022/06/22/Redis切片集群的数据倾斜分析/
Redis 切片集群的数据倾斜分析的更多相关文章
- Redis Cluster集群知识学习总结
Redis集群解决方案有两个: 1) Twemproxy: 这是Twitter推出的解决方案,简单的说就是上层加个代理负责分发,属于client端集群方案,目前很多应用者都在采用的解决方案.Twem ...
- 用redis-dump工具对redis集群所有数据进行导出导入
安装redis-dump redis-dump是基于ruby开发,需要ruby环境,而且新版本的redis-dump要求2.2.2以上的ruby版本,centos中yum只能安装2.0版本的ruby. ...
- 在 Istio 中实现 Redis 集群的数据分片、读写分离和流量镜像
Redis 是一个高性能的 key-value 存储系统,被广泛用于微服务架构中.如果我们想要使用 Redis 集群模式提供的高级特性,则需要对客户端代码进行改动,这带来了应用升级和维护的一些困难.利 ...
- 借 redis cluster 集群,聊一聊集群中数据分布算法
Redis Cluster 集群中涉及到了数据分布问题,因为 redis cluster 是多 master 的结构,每个 master 都是可以提供存储服务的,这就会涉及到数据分布的问题,在新的 r ...
- Redis之集群
Redis Cluster是 Redis的分布式解决方案,在3.0版本正式推出,有效地解决了Redis分布式方面的需求.当遇到单机内存.并发.流量等瓶颈时,可以采用Cluster架构方案达到负载均衡的 ...
- 02.Redis主从集群的Sentinel配置
1.集群环境 1.Linux服务器列表 使用4台CentOS Linux服务器搭建环境,其IP地址如下: 192.168.110.100 192.168.110.101 192.168.110.102 ...
- 10.Redis分布式集群
10.Redis分布式集群10.1 数据分布10.1.1 数据分布理论10.1.2 Redis数据分区10.1.3 集群功能限制10.2 搭建集群10.2.1 准备节点10.2.2 节点握手10.2. ...
- redis sentinel集群的搭建
背景说明: 这里采用1主2从的redis集群,3个sentinel搭建高可用redis集群. 一,关于搭建redis-sentinel高可用之前,我们必须要了解redis主从搭建redis-senti ...
- centos6下redis cluster集群部署过程
一般来说,redis主从和mysql主从目的差不多,但redis主从配置很简单,主要在从节点配置文件指定主节点ip和端口,比如:slaveof 192.168.10.10 6379,然后启动主从,主从 ...
随机推荐
- Cookie&&Session&&jsp入门
会话技术 会话:一次会话中包含多次请求和响应. 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止 功能:在一次会话的范围内的多次请求间,共享数据 方式: 客户端会话技术:Coo ...
- flex布局 (转)
网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中 ...
- 踹掉后端,前端导出Excel!
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一个下载链接,但有时候我们只想导出前端页面上已经有了的数据,不想再调后端导出接口浪费服务器资源,学习本文demo例子,我们踹掉后端,直接在前 ...
- Jenkins Build step 'Execute shell' marked build as failure
问题出现: Jenkins一直都构建成功,今天突然报错:Jenkins Build step 'Execute shell' marked build as failure 问题原因: By defa ...
- ZABBIX新功能系列1-使用Webhook将告警主动推送至第三方系统
Zabbix5以来的新版本与以前的版本除UI界面变化较大外,在很多功能上也有许多亮点,我这里计划安排1个系列来和大家交流一些新功能的使用,这是第一篇:使用Webhook将告警主动推送至第三方系统. 首 ...
- 【LINT】cpplint修改版:自定义编码风格检查工具lint
github:https://github.com/skullboyer/code-check Code Check 本仓介绍的内容涉及代码静态检查和编码风格检查 但主要放在编码风格检查,lint是基 ...
- js实时查询,为空提示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- python二分法、牛顿法求根
二分法求根 思路:对于一个连续函数,左值f(a)*右值f(b)如果<0,那么在这个区间内[a,b]必存在一个c使得f(c)=0 那么思路便是取中间点,分成两段区间,然后对这两段区间分别再比较,跳 ...
- 云厂商 RDS MySQL 怎么选
1. 摘要 为了让大家更好的了解各云厂商在RDS MySQL数据库功能上的差异,也为给准备上云的同学做个参考,本文将对阿里云.腾讯云.华为云和AWS 的 RDS MySQL数据库进行对比说明. 从一个 ...
- [保姆级教程] 如何在 Linux Kernel (V5.17.7) 中添加一个系统调用(System call)
最近在学习 <linux Kernel Development>,本书用的linux kernel 是v2.6 版本的.看完"系统调用"一节后,想尝试添加一个系统调用, ...