redis的集群只要有三种:
Redis主从:主从又分单副本和多副本,单副本也就是只有主机;多副本也就是常说的主从复制
Redis Sentinel(哨兵)
Redis Cluster
一.Redis主从模式:
单机模式:
这种单机模式一般只适用于程序员自己开发测试使用,没有备用节点实时同步数据,如果要运用于工作中的话一般是在不提供数据持久化和备份策略,数据可靠性要求不高的纯缓存业务场景。
优点:
架构简单,部署方便;
缺点:
不保证数据的可靠性;
不适用于数据可靠性要求高的业务;
高性能受限于单核 CPU 的处理能力(Redis 是单线程机制),CPU 为主要瓶颈,所以适合操作命令简单,排序、计算较少的场景。也可以考虑用 Memcached 替代。
多机模式:
Redis 多副本,采用主从(replication)部署结构,主从实例间数据实时同步,并且提供数据持久化和备份策略。主从实例部署在不同的物理服务器上,根据公司的基础环境配置,可以实现同时对外提供服务和读写分离策略。
多机模式需要了解和知道的东西就要更清楚一些:
1.主从之间同步数据是怎么一个过程?
2.主机挂掉,从机是怎么去接替主机?
3.从机接替主机之后,主机又重启之后是在什么位子呢?
首先了解第一个问题:数据同步的过程
两个redis地址:127.0.0.1:6379 和 127.0.0.1:12345,客户端向服务器127.0.0.1:12345发送命令: SLAVEOF 127.0.0.1 6379
12345端口就会成为6379的从服务器然后开始进行复制,整个复制过程如下:
1.从数据库向主数据库发送sync命令;
2.主数据库收到sync命令后,便开始执行bgsave命令(该命令干了些什么可以看我上一篇关于持久化的博客),在后台保存快照,生成rdb文件,然后在生成快照文件的同时收到的命令请求会缓存在缓冲区,等到快照过程结束,主数据库会把快照和缓冲区数据一起发送给从数据库。(《redis设计与实现》书中的图片)
整个过程完成之后,主数据库每收到1个命令就同步发送给从数据库。当出现断开重连后,会将断线期间的命令传给重数据库(2.8以前的旧版是每次都全量复制)。增量复制主从复制是乐观复制,当客户端发送写执行给主,主执行完立即将结果返回客户端,并异步的把命令发送给从,从而不影响性能。也可以设置至少同步给多少个从主才可写。
sync是一个非常消耗性能的命令,在2.8版本之后出现了新的命令:PSYNC命令来代替SYNC命令;PSYNC命令有完整同步和部分同步功能;
图中的CONTINUE是一个复制偏移量的计算结果;那什么是复制偏移量;
主从服务器都会维护一个偏移量,而在同步的时候会更新各自服务器上的偏移量;如果某一个从服务器挂掉,那根据偏移量就很容易知道该主从服务器是否处于一致的状态;
从服务器会重新启动连接上主服务器时,会通过PYSNC把自己的偏移量发送给主服务器,主服务器会根据偏移量来决定执行何种同步操作;
决定何种同步操作的时候又涉及到一个知识点:复制积压缓冲区
这是一个由主服务器维护的一个固定长度队列,大小为1MB(大小可在配置文件中修改);
如果从服务器连接上主服务器之后,偏移量大于这个积压缓冲区的数据保存量,则主服务器选择完整同步操作;
如果偏移量小于积压缓冲区的数据保存量,则选择部分同步操作;
下图展示了整个PSYNC的过程:
然后是第二和第三个问题:主机挂掉,从机如何接替主机,主机重新启动后又怎么处理
第一步,在从数据库中执行SLAVEOFNO ONE命令,断开主从关系并且提升为主库继续服务;(这一步需要手动实现,如果在哨兵模式下,则会自己实现该功能)
第二步,将主库重新启动后,执行SLAVEOF命令,将其设置为其他库的从库,这时数据就能更新回来;
二.Redis Sentinel(哨兵):
先理解下什么是哨兵模式吧。
当server1的下线时候超过管理员设定的时长时,sentinel系统会对server1执行故障转移操作:
1.sentinel系统会挑选从服务器中的一个成为主服务器对象(选举过程下面在讲);
2.sentinel系统会向剩下的所有从服务器发送复制命令,让他们从未新主服务器的从服务器,当所有从服务器开始复制新的主服务器时,故障转移工作算执行完毕了;
3.sentinel还会一直监视下面的server1,如果上线则会把他设置成为新主服务器的从服务器;
哨兵模式可以说是主从模式的高阶版;再次提出问题(面试的时候面试官问过下面两个问题):
1.如何设置成哨兵模式?
在客户端执行 redis-sentinel /path/to/your/sentinel.conf
一个sentinel启动时经过如下过程:
把普通redis服务器的使用代码替换成sentinel专用代码
根据给的的配置文件,初始化sentinel监视主服务器列表
创建连接主服务器的连接。
注:图出自《redis设计与实现》
说白了sentinel就是一个特殊的redis服务器,但是这个服务器不需要数据库使用,也就是说初始化的时候不需要加载rdb或者aof文件
sentinel模式下,服务器用不了很多的命令是因为服务器启动的时候没有在命令表中加载这些命令。
新的主服务器选举过程:
三.Redis Cluster(分片集群):
分布式集群解决方案,当遇到单机内存,并发和流量等瓶颈的时候,Redis Cluster 能起到很好的负载均衡的目的。
在主从和哨兵模式中redis每个实例也是全量存储,每个redis存储的内容都是完整的数据,浪费内存且有木桶效应。为了最大化利用内存,可以采用集群,就是分布式存储。即每台redis存储不同的内容。
设置集群过程:
客户端向一个节点node发送CLUSTER MEET <ip> <port> ,让节点与ip和port所指定的节点进行握手,握手成功则node、节点就会将该节点添加到node节点当前所在的集群中;
集群模式下的服务器也是一个普通的redis服务器,只是在启动的时候进行了一个配置选项是否决定开启服务器的集群模式。节点在运行集群模式下,单机模式下的使用服务器组件会继续使用。
在集群模式下有一个非常重要知识点:
槽指派(slot)
那有多少个槽呢,一共有16383个槽;
在集群中存入一个key-value,首先key进过CRC16算法和16384取余,得到的结果回对应到0-16383之间的哈希槽上,然后就存入映的哈希槽中;
在获取数据时,当一个client向集群中的其中一个node发送get命令,接收到该命令的node会计算要处理的key所属的哈希槽,根据计算出的结果进行三步:
1.检查哈希槽是否属于本node管辖哈希槽,如果key所在槽刚好是自己的管辖区,则该node执行该命令;
2.如果不在该node中,该node会返回一个MOVED错误,指引client转向负责该对应哈希槽的node,然后客户端需要再次发送想要执行的key命令。
(MOVED返回的格式是:MOVED 6257 127.0.0.1:7001 ,其中6257指的是哈希槽)
(说明:本人刚开始学习的时候一直以为一个哈希槽只能存一个key的相关数据,然后16384个槽也就只能存这么多key,后来想想不可能;然后知道一个哈希槽中会有N多个key-value值,可以把这样一个槽理解成表的分区,开启集群模式之后,就会自动生成16384个分区,然后会根据设定好的算法决定哪些哈希槽在那个node上)
那为什么哈希槽要设定成16384个呢?
这个问题我就直接附上链接,想了解的同学可以自己去学习研究。简单说一下就是集群之间需要发送心跳包,让心跳包小一点才设置成16384的
为什么Redis集群有16384个槽?_沐雨金鳞-CSDN博客blog.csdn.net这个slot数组是一个bitmap数组,大小为16384/8 = 2048个字节。
每个服务器通过发送消息让其他的所有服务器知道自己负责的是哪些哈希槽。
在集群模式中还有一个重要的操作就是:重新分片
重新分片的意思就是把已经指派给某个node的槽改为指派给另一个node,并且相关槽上所有key-value值都会被转移到新node上;
每次转移该槽中的一个key-vaule值都会重复图中的3和4两个步骤。
一般在集群模式下还会使用主从的方式,主机复制处理槽,而从机用于复制主机数据,如果主机出现故障,则会进行故障转移,用从机成为新的主机;如果故障主机重新上线会成为新主机的从机。
最后再讲一下如果搭建redis集群:
集群最少三个node,而每个node需要有主从,所以也就需要6个node,
然后再每个节点下的redis.conf文件中修改开启集群模式,然后分别启动6个redis。
具体的细节,大家可以在网上百度下,这里就不细讲了。