redis如何避免数据倾斜
数据倾斜分类
数据量倾斜
在某些情况下,实例上的数据分布不均衡,某个实例上的数据特别多。
造成原因
1、bigKey
bigkey 的 value 值很大(String 类型),或者是 bigkey 保存了大量集合元素(集合类型),会导致这个实例的数据量增加,内存资源消耗也相应增加。bigkey 的操作一般都会造成实例 IO 线程阻塞,如果 bigkey 的访问量比较大,就会影响到这个实例上的其它请求被处理的速度。
在生成数据时,尽量避免把过多的数据保存在同一个键值对中,如果bigKey是一个集合,我们可以把bigKey拆分成多个小的集合类型,分散保存在不同实例。
2、slot分配不均衡
如果集群运维人员没有均衡地分配 Slot,就会有大量的数据被分配到同一个 Slot 中,而同一个 Slot 只会在一个实例上分布,这就会导致,大量数据被集中到一个实例上,造成数据倾斜。
比如说,集群中有5个实例,而实例1的硬件配置比较好,可能分配人员就给实例1多分配了几个Slot。但并不知道数据和Slot的对应关系,这种做法就有可能导致大量数据被映射到实例1的slot上。
在分配前,可以避免把过多的slot分配到一个实例上。如果已经分配了的,可以查看是否把同一个实例上分配了过多的slot,如果分配就将部分slot进行迁移。
3、Hash Tag
Hash Tag 是指加在键值对 key 中的一对花括号{}。这对括号会把 key 的一部分括起来,客户端在计算 key 的 CRC16 值时,只对 Hash Tag 花括号中的 key 内容进行计算。如果没用 Hash Tag 的话,客户端计算整个 key 的 CRC16 的值。
假设 key 是 user:profile:3231,我们把其中的 3231 作为 Hash Tag,此时,key 就变成了 user:profile:{3231}。当客户端计算这个 key 的 CRC16 值时,就只会计算 3231 的 CRC16 值。
使用 Hash Tag 的好处是,如果不同 key 的 Hash Tag 内容都是一样的,那么,这些 key 对应的数据会被映射到同一个 Slot 中,同时会被分配到同一个实例上。
Hash Tag主要是用在 Redis Cluster 和 Codis 中,支持事务操作和范围查询。因为 Redis Cluster 和 Codis 本身并不支持跨实例的事务操作和范围查询(多个Redis进行范围查询或者事务操作),当业务应用有这些需求时,就只能先把这些数据读取到业务层进行事务处理,或者是逐个查询每个实例,得到范围查询的结果。我们可以使用 Hash Tag 把要执行事务操作或是范围查询的数据映射到同一个实例上,这样就能很轻松地实现事务或范围查询了。
数据访问倾斜
虽然每个集群实例上的数据量相差不大,但是某个实例上的数据是热点数据,被访问得非常频繁。
发生数据访问倾斜的根本原因,就是实例上存在热点数据。我们可以采用热点数据多副本的方法来应对。具体就是在每一个副本key中增加一个随机前缀,让它和其他副本分配到不同的slot中。热点数据多副本方法只能针对只读的热点数据。