本文首发于公众号:程序员周先森。本平台不定期更新,喜欢我的文章,请关注我的微信公众号。前两篇介绍了Redis主从复制和主从切换的知识点,但是也很明显有个小缺点:需要定期主从复制会影响Redis的性能。主节点宕机后,选择所有从节点进行主从切换。主从切换时非服务不可用。引入分片的概念——分片机制的作用。本文主要讲Redis的sharding机制。如果没有分片机制,Redis受限于单机支持的内存容量。Redis的分片机制允许数据被拆分并存储在不同的Redis实例上,每个Redis实例只包含所有键的一个子集。可以减轻单个Redis的压力,提高Redis的扩展和计算能力。如果我们只使用一个Redis实例,当Redis宕机时会直接停止服务,所以我们可以采用分片机制,将一个Redis实例维护的数据改为由多个Redis实例共同维护。Sharding方案(1)RangeshardingSharding需要将不同的key映射到不同的Redis实例上进行存储,所以需要制定key映射规则的算法。最简单的分片方案应该是范围分片。范围分片很容易理解。比如我们存储用户基本信息,我们制定一个算法,将user_id从0到1000映射到实例A,user_id从1000到2000映射到实例B,等等。这个解决方案很容易使用,但它提出了一个问题:我们需要维护user_id范围和映射实例之间的关系。正是这个问题使得范围分片变得简单,但比其他分片方案效率低得多。因此,范围分片一般不作为Redis中的分片方案。(2)Hash分片比如我们目前有4个Redis实例,需要存储一个key。我们可以使用哈希函数crc32()将键名转换成一个长整型数,然后对这个长整型数取模4得到映射的实例。但是这种分配方案也有缺点:当我们需要添加或移除Redis实例时,会导致大量的键命中失败。所以这个时候出现了哈希分片的一种高级形式——一致性哈希。一致性哈希具有三大特点:Key哈希结果尽可能分布到不同的Redis实例。添加或删除实例时,有必要保护映射内容不被重新分配给新实例。密钥的散列应尽量避免重复。但是Redis中并没有使用一致性哈希的概念,而是引入了哈希槽。Redis集群中有16384个hash槽,然后每个key通过hash函数crc16()将key名转换成一个长整型数,然后取16384的余数,最终确定存放key的hash槽。每个Redis实例负责维护一些哈希槽,所有实例共同维护所有哈希槽。使用hashslots最明显的特点就是可以非常方便的增加或移除Redis实例,而无需暂停所有Redis实例服务。分片实现上一篇关于主从切换哨兵模式的文章提到过,哨兵模式可以实现高可用和读写分离,但是缺点是所有Redis实例存储的数据都是一致的,所以Redis支持cluster模式,可以简单的理解为Cluster是Redis集群管理的一个插件,通过它可以实现Redis的分布式存储。数据分片一般分为三种:客户端分片、代理分片和服务器分片。客户端分片的定义:客户端计算key需要映射到哪个Redis实例。优点:客户端分片最明显的好处是降低了集群的复杂度,服务器之间没有关联,客户端负责实现数据分片。缺点:如果客户端实现分片,客户端需要知道当前集群中不同Redis实例的信息。添加新的Redis实例时,需要支持动态分片。大多数Redis需要重启才能实现这个功能。代理分片定义:客户端向代理发送请求,代理通过计算得到需要映射的集群实例信息,然后将客户端的请求转发给对应的集群实例,然后返回响应给客户端。优点:降低了客户端的复杂度,客户端不需要关心后端Redis实例的状态信息。缺点:多了一个中间分发环节,因此在性能上有一些损失。服务器分片定义:客户端可以与集群中的任何Redis实例进行通信。当客户端访问一个实例时,服务端会计算该key应该映射到哪个具体的Redis实例进行存储。如果映射的实例不是当前实例,该实例会主动引导客户端对该实例对应的key进行操作。这实际上是一个重定向过程。这个过程并不是从当前的Redis实例转发到对应的Redis实例,而是服务端通知客户端将具体映射的Redis实例重定向到映射的实例。目前还不能完全适用于生产环境。优点:支持高可用,任何实例都有master和slave,master挂了slave会自动接管。缺点:需要客户端语言来实现服务器集群协议,但是目前大部分语言都有自己的客户端实现。Pre-sharding从上面可以明显看出,通过分片机制来增删实例是非常麻烦的,所以我们可以考虑一开始就开启32个节点的实例。当我们可以添加一个新的Redis服务器时,我们就有可能将一半的节点移动到一个新的Redis服务器上。这样我们只需要在新服务器上启动一个空节点,然后移动数据,将新节点配置为源节点的从节点,然后更新被移动节点的ip信息,然后发送slaveof命令到新服务器关闭主从配置,最后关闭老服务器不需要使用实例,重启客户端。这使我们能够在几乎没有停机时间的情况下移动数据。分片机制的缺点分片是由多个Redis实例运行的,如果其中一个Redis实例宕机,整个分片将不可用,分片机制无法实现高可用。如果不同的键映射到不同的Redis实例,此时不能对这两个键进行交叉或使用事务。使用分片机制涉及复杂的数据处理,因为涉及多个实例。分片中实例的增删会比较复杂,但可以通过预分片技术进行改进。欢迎关注公众号:程序员周先森。本文由博客多发平台OpenWrite发布!
