参考
https://www.cnblogs.com/cjsblog/p/9553850.html
https://blog.csdn.net/tianmangshan80/article/details/51704974
https://blog.csdn.net/rosanu_blog/article/details/68066756
redis集群
分为服务端集群
和客户端分片
,redis3.0以上版本实现了集群机制,即服务端集群,3.0以下使用客户端分片(Sharding)。redis3.0服务端集群使用哈希槽,计算key的CRC16结果再模16834。3.0以下版本采用Key的一致性hash算法来区分key存储在哪个Redis实例上。
Redis分区,简单的说就是将数据分布到不同的redis实例中,因此对于每个redis实例所存储的内容仅仅是所有内容的一个子集。分区(Partitioning)不仅仅是Redis中的概念,几乎是所有数据存储系统都会涉及到的概念,这篇文章将会在理解分区基本概念的基础之上进一步了解Redis对分区的支持。
通常来说,Redis分区的好处大致有如下两个方面:
计算能力
和网络带宽
,有助于提高Redis总体的服务能力。存储容量
,将数据分散到多台机器上存储,使得Redis服务可以横向扩展。总的来说,分区使得我们本来受限于单台计算机硬件资源的问题不再是问题,存储、计算资源、带宽等问题,都可以通过增加机器来解决这些问题。
所谓范围分区,就是将一个范围内的key都映射到同一个Redis实例中。
假设我们有4个Redis实例(R0, R1, R2, R3),其上有许多代表用户的key,比如user:1, user:2, … 等等,那么在存储一个key的时候我们有多种方式。
我们可以将用户ID从0到10000的用户数据映射到R0实例,而将用户ID从10001到20000的对象映射到R1实例,依次类推。
范围分区的优点: 虽然简单,但是在实际应用中是很有效的。
范围分区的缺点:
映射关系表
,例如需要一张表用来存储用户ID范围到Redis实例的映射关系
,比如用户ID:0-10000的是映射到R0实例……。因此,在实际应用中,范围分区并不是很好的选择,不用担心,我们还有更好的方法,接下来认识下哈希分区。
哈希分区跟范围分区相比一个明显的优点是哈希分区适合任何形式的key
,而不像范围分区一样需要key的形式为object_name:,而且哈希分区方法也很简单,一个公式就可以表达:id=hash(key)%N
。
其中id代表Redis实例的编号,公式描述的是首先根据key和一个hash函数(如crc32函数)计算出一个数值型的值。接着上面的例子,我们的第一个要处理的key是user:1,hash(user:1)的结果是93024922。
然后哈希结果进行取模,取模的目的是计算出一个介于0到3之间的值,因此这个值才可以被映射到我们的一台Redis实例上面。比如93024922%4结果是2,我们就会知道foobar将要被存储在R2上面。
当然除了上面提到的两种分区方法,还有很多其他的方法。比如一种从哈希分区演进而来的consistent hashing分区,相关信息可以参考我的另一篇文章《memcached分布式实现原理》,其已经被redis client客户端和proxies代理实现了。
根据余数计算分散的缺点
余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点。那就是当添加或移除服务器时,缓存重组的代价相当巨大。 添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器
, 从而影响缓存的命中率,负载会集中到数据库服务器上。
重定向
到正确的服务器。presharding
的技术对此是有帮助的。解决单点故障的方法:
用到Redis主从复制的功能,两台物理主机上分别都运行有Redis-Server,其中一个Redis-Server是另一个的从库,采用双机热备技术
,客户端通过虚拟IP访问主库的物理IP,当主库宕机时,切换到从库的物理IP。只是事后修复主库时,应该将之前的从库改为主库(使用命令slaveof no one),主库变为其从库(使命令slaveof IP PORT),这样才能保证修复期间新增数据的一致性。一致哈希
很容易进行伸缩。如果给定key的首选节点不可用,一致哈希实现通常能够切换到其他节点。一个固定的key到实例的映射是需要的
。给定的key必须总是映射到相同的Redis实例,因此节点的数量必须是固定的,且不能改变。否则,就需要一个能够在节点之间重新平衡key的系统,当前Redis集群是可以做到这一点的。通过上面的介绍,我们知道Redis分区应用起来是有问题的,除非我们只是使用Redis当做缓存,否则对于增加机器或删除机器是非常麻烦的。
然而,通常我们Redis容量变动在实际应用中是非常常见的,比如今天我需要10台Redis机器,明天可能就需要50台机器了。
Redis的作者提出了一种叫做presharding
的方案来解决动态扩容和数据分区的问题
,实际就是在同一台机器上部署多个Redis实例的方式,当容量不够时将多个实例拆分到不同的机器上,这样实际就达到了扩容的效果。Pre-Sharding方法是
在每台物理机上,运行多个不同端口
的Redis实例,假如有三个物理机,每个物理机运行三个Redis实例,那么我们的分片列表中实际有9个Redis实例,当我们需要扩容时,增加一台物理机来代替9个中的一个redis,有人说,这样不还是9个么,是的,但是以前服务器上面有三个redis,压力很大的,这样做,相当于单独分离出来并且将数据一起copy给新的服务器。值得注意的是,还需要修改客户端被代替的redis的IP和端口为现在新的服务器,只要顺序不变,不会影响一致性哈希分片
。
怎么移动Redis实例呢? 当需要将Redis实例移动到独立的机器上的时候,我们可以通过下面步骤实现:
如果主库快照数据文件过大,这个复制的过程也会很久,同时会给主库带来压力。所以做这个拆分的过程最好选择为业务访问低峰时段进行
。