分区的定义和意义
分区是将数据拆分到多个Redis实例的过程,因此每个实例将只包含所有键的一个子集。
对Redis进行分区有两个主要目标:
- 它允许使用多台计算机的内存总和来创建更大的数据库。 如果不进行分区,则只能使用一台计算机可以支持的内存量,而一台计算机的内存是有限的。
- 它允许将计算能力扩展到多核和多台计算机,并将网络带宽扩展到多台计算机和网络适配器。
范围分区
架设我们有四个Redis实例R0,R1,R2,R3和许多表示用户的键,例如user:1,user:2,...等,我们可以使用不同的方法来选择在哪个实例中存储给定的键。换句话说,将给定key映射到给定Redis服务器的方法有很多种。 执行分区的最简单方法之一是范围分区,它是通过将对象范围映射到特定Redis实例中来实现的。例如,我可以说从ID 0到ID 10000的用户将进入实例R0,而从ID 10001到ID 20000的用户将进入实例R1,依此类推。 这种方式是可行的,并且在实际中使用,但是它的缺点是需要一个将范围映射到实例的表。需要管理该表,并且每种对象都需要一个表,因此Redis中的范围分区通常并不是个好的方案,因为它比其他替代分区方法效率低得多。
哈希分区
一种可以替代范围分区的方法是哈希分区。 此方案适用于任何键,而无需使用object_name:<id>形式的键,并且非常简单:
- 获取key名称并使用哈希函数(例如crc32哈希函数)将其转换为数字。 例如,如果key是foobar,则crc32(foobar)将输出类似93024922的信息。
- 对这个数字使用取模运算,以便将其转换为0到3之间的数字,以便可以将该数字映射到我的四个Redis实例之一。 93024922模4等于2,所以我知道我的密钥foobar应该存储到R2实例中。
注意:模运算返回除法运算的余数,并以%运算符在许多编程语言中实现。 还有许多其他方法可以执行分区,但是通过这两个示例,您应该会明白。 哈希分区的一种高级形式称为一致哈希,由一些Redis客户端和代理实现。
分区的不足
redis的一些特性在分区方面表现的不是很好:
- 涉及多个key的操作通常是不被支持的。举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。
- 涉及多个key的redis事务不能使用。
- 当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。
- 增加或删除容量也比较复杂。redis集群大多数支持在运行时增加、删除节点的透明数据平衡的能力,但是类似于客户端分区、代理等其他系统则不支持这项特性。然而,一种叫做presharding的技术对此是有帮助的。