前语

在切片集群中,数据会依照一定的散布规矩涣散到不同的实例上保存。比如,在运用 Redis Cluster 或 Codis 时,数据都会先依照 CRC 算法的核算值对 Slot(逻辑槽)取模,同时,所有的 Slot 又会由运维管理员分配到不同的实例上。这样,数据就被保存到相应的实例上了。

尽管这种办法实现起来比较简单,可是很简单导致一个问题:数据歪斜。

数据歪斜的种类

数据歪斜有两类

  • 数据量歪斜:在某些情况下,实例上的数据散布不均衡,某个实例上的数据特别多。
  • 数据拜访歪斜:尽管每个集群实例上的数据量相差不大,可是某个实例上的数据是热门数据,被拜访得十分频频。

数据量歪斜的成因及应对办法

当数据量歪斜发生时,数据在切片集群的多个实例上散布不均衡,很多数据会集到了一个或几个实例上。

Redis 集群如何应对数据倾斜

那么,数据量歪斜是怎样发生的呢?这主要有三个原因,分别是某个实例上保存了 bigkey、Slot 分配不均衡以及 Hash Tag。

bigkey

某个实例上正好保存了 bigkey。bigkey 的 value 值很大(String 类型),或者是 bigkey 保存了很多调集元素(调集类型),会导致这个实例的数据量添加,内存资源消耗也相应添加。

一个底子的应对办法是,咱们在事务层生成数据时,要尽量防止把过多的数据保存在同一个键值对中

此外,假如 bigkey 正好是调集类型,咱们还有一个办法,就是把 bigkey 拆分成很多个小的调集类型数据,涣散保存在不同的实例上。

Slot 分配不均衡

假如集群运维人员没有均衡地分配 Slot,就会有很多的数据被分配到同一个 Slot 中,而同一个 Slot 只会在一个实例上散布,这就会导致,很多数据被会集到一个实例上,形成数据歪斜。

为了应对这个问题,咱们能够通过运维规范,在分配之前,咱们就要防止把过多的 Slot 分配到同一个实例。

不同集群上检查 Slot 分配情况的办法不同:假如是 Redis Cluster,就用 CLUSTER SLOTS 指令;假如是 Codis,就能够在 codis dashboard 上检查。

Slot 搬迁

假如是已经分配好 Slot 的集群,咱们能够先检查 Slot 和实例的详细分配关系,然后判别是否有过多的 Slot 会集到了同一个实例。假如有的话,就将部分 Slot 搬迁到其它实例,然后防止数据歪斜。

在 Redis Cluster 中,咱们能够运用 3 个指令完结 Slot 搬迁。

  • CLUSTER SETSLOT:运用不同的选项进行三种设置,分别是设置 Slot 要迁入的方针实例,Slot 要迁出的源实例,以及 Slot 所属的实例。
  • CLUSTER GETKEYSINSLOT:获取某个 Slot 中一定数量的 key。
  • MIGRATE:把一个 key 从源实例实践搬迁到方针实例。

HashTag

Hash Tag 是指加在键值对 key 中的一对花括号{}。这对括号会把 key 的一部分括起来,客户端在核算 key 的 CRC16 值时,只对 Hash Tag 花括号中的 key 内容进行核算。假如没用 Hash Tag 的话,客户端核算整个 key 的 CRC16 的值。

运用 Hash Tag 的优点是,假如不同 key 的 Hash Tag 内容都是相同的,那么,这些 key 对应的数据会被映射到同一个 Slot 中,同时会被分配到同一个实例上。

那么,Hash Tag 一般用在什么场景呢?其实,它主要是用在 Redis Cluster 和 Codis 中,支持事务操作和范围查询。因为 Redis Cluster 和 Codis 自身并不支持跨实例的事务操作和范围查询,当事务运用有这些需求时,就只能先把这些数据读取到事务层进行事务处理,或者是逐一查询每个实例,得到范围查询的成果。

可是,运用 Hash Tag 的潜在问题,就是很多的数据或许被会集到一个实例上,导致数据歪斜,集群中的负载不均衡。 那么,该怎样应对这种问题呢?咱们就需要在范围查询、事务履行的需求和数据歪斜带来的拜访压力之间,进行取舍了。

我的建议是,假如运用 Hash Tag 进行切片的数据会带来较大的拜访压力,就优先考虑防止数据歪斜,最好不要运用 Hash Tag 进行数据切片。因为事务和范围查询都还能够放在客户端来履行,而数据歪斜会导致实例不稳定,形成服务不可用。

数据拜访歪斜的成因和应对办法

一旦热门数据被存在了某个实例中,那么,这个实例的恳求拜访量就会远高于其它实例,面对巨大的拜访压力。

Redis 集群如何应对数据倾斜

一般来说,热门数据以服务读操作为主,在这种情况下,咱们能够采用热门数据多副本的办法来应对。

这个办法的详细做法是,咱们把热门数据复制多份,在每一个数据副本的 key 中添加一个随机前缀,让它和其它副本数据不会被映射到同一个 Slot 中。这样一来,热门数据既有多个副本能够同时服务恳求,同时,这些副本数据的 key 又不相同,会被映射到不同的 Slot 中。

在给这些 Slot 分配实例时,咱们也要留意把它们分配到不同的实例上,那么,热门数据的拜访压力就被涣散到不同的实例上了。

热门数据多副本办法只能针对只读的热门数据。假如热门数据是有读有写的话,就不合适采用多副本办法了,因为要保证多副本间的数据一致性,会带来额外的开支。

对于有读有写的热门数据,咱们就要给实例自身添加资源了,例如运用装备更高的机器,来应对很多的拜访压力。

总结

Redis 集群如何应对数据倾斜

在构建切片集群时,尽量运用大小装备相同的实例(例如实例内存装备坚持相同),这样能够防止因实例资源不均衡而在不同实例上分配不同数量的 Slot。

参阅

摘自 极客时刻 – 蒋德钧教师的《Redis 核心技术与实战》 <- 极其引荐我们阅览~

《Redis 核心技术与实战》学习笔记 Day7