redis的主从复制,哨兵和cluster集群

news2025/7/12 7:33:22

一、redis性能管理

(1) redis-cli
 127.0.0.1:6379> info memory
 ​
 
 (2) redis-cli info memory

  • used_memory_rss:是Redis向操作系统申请的内存。
  • used_memory:是Redis中的数据占用的内存。
  • used_memory_peak:redis内存使用的峰值。

1.2内存碎片

内存碎片率=Redis向操作系统申请的内存 / Redis中的数据占用的内存

mem_fragmentation_ratio = used_memory_rss / used_memory

mem_fragmentation_ratio:内存碎片率。

redis-cli info memory |grep ratio
 

内存碎片产生的原因

  • Redis内部有自已的内存管理器,为了提高内存使用的效率,来对内存的申请和释放进行管理。
  • Redis中的值删除的时候,并没有把内存直接释放、交还给操作系统,而是交给了Redis内部有内存管理器。
  • Redis中申请内存的时候,也是先看自己的内存管理器中是否有足够的内存可用。
  • Redis的这种机制,提高了内存的使用率,但是会使Redis中有部分自己没在用,却不释放的内存,导致了内存碎片的发生。

内存碎片率对redis的影响 

  • 内存碎片率在1到1.5之间是正常的,这个值表示内存碎片率比较低,也说明Redis 没有发生内存交换。
  • 内存碎片率超过1.5,说明Redis消耗了实际需要的物理内存的150%,其中50%是内存碎片率。
  • 内存碎片率低于1的,说明Redis内存分配超出了物理内存,操作系统正在进行内存交换(使用虚拟内存,会降低性能)。需要增加可用物理内存或减少Redis内存占用。

解决碎片率过大的方法 

  • 如果你的Redis版本是4.0以下的,需要在redis-cli 工具上输入shutdown save命令,让Redis数据库执行保存操作并关闭Redis服务,再重启服务器。Redis服务器重启后,Redis 会将没用的内存归还给操作系统,碎片率会降下来。
  • Redis4.0版本开始,可以在不重启的情况下,线上整理内存碎片,将未使用的内存归还给操作系统。

 config set activedefrag yes    #自动碎片清理
 memory purge                   #手动碎片清理

 1.3内存使用率 

redis实例的内存使用率超过可用最大内存,操作系统将开始进行内存与swap空间交换。

避免内存交换发生的方法:

  • 针对缓存数据大小选择安装Redis 实例
  • 尽可能的使用Hash数据结构存储
  • 设置key的过期时间

1.4内回收key 

存清理策略,保证合理分配redis有限的内存资源。

当内存使用达到设置的最大阈值时,需选择一种key的回收策略,默认情况下回收策略是禁止删除(noenviction)。配置文件中修改 maxmemory-policy 属性值:

im /etc/redis/6379.conf
 ---598行----
 maxmemory-policy noenviction   #修改max-memory-policy属性值
 ​
 ##回收策略有以下几种:##
 ●volatile-lru
 #使用LRU算法从已设置过期时间的数据集合中淘汰数据
 (移除最近最少使用的key,针对设置了TTL的key)
 ​
 ●volatile-ttl
 #从已设置过期时间的数据集合中挑选即将过期的数据淘汰
 (移除最近过期的key)
 ​
 ●volatile-random
 #从已设置过期时间的数据集合中随机挑选数据淘汰
 (在设置了TTL的key里随机移除)
 ​
 ●allkeys-lru
 #使用LRU算法 从所有数据集合中淘汰数据
 (移除最少使用的key,针对所有的key)
 ​
 ●allkeys-random
 #从数据集合中任意选择数据淘汰(随机移除key)
 ​
 ●noenviction
 #禁止淘汰数据(不删除直到写满时报错)

二、redis的优化策略

2.1设置Redis客户端连接的超时时间 

vim /etc/redis/6379.conf
 -----114行------
 114 timeout 0     
 #单位为秒(s),取值范围为0~100000。默认值为0,表示无限制,即Redis不会主动断开连接,即使这个客户端已经空闲了很长时间。
 #例如可设置为600,则客户端空闲10分钟后,Redis会主动断开连接。
 ​
 #注意:在实际运行中,为了提高性能,Redis不一定会精确地按照timeout的值规定的时间来断开符合条件的空闲连接,例如设置timeout为10s,但空闲连接可能在12s后,服务器中新增很多连接时才会被断开。

2.2 设置redis自动碎片清理

 config set activedefrag yes    #自动碎片清理
 memory purge                   #手动碎片清理

2.3设置redis最大内存阈值 

内存阈值如果不设置,则没有限制,直到把服务器的内存干满、之后会使用交换分区。

设置内存阈值后,不会使用swap交换分区。且如果设置了key回收策略,当内存使用达到设置的最大阈值时,系统会进行key回收。

vim /etc/redis/6379.conf
 -----567行------
 567 # maxmemory <bytes>
 568 maxmemory 1gb           #例如设置最大内存阈值为1gb

三、redis雪崩、穿透、击穿的原因和解决方案

(1) redis雪崩

定义:缓存雪崩是指大量的应用请求无法在 Redis 缓存中进行处理,紧接着,应用将大量请求发送到数据库层,导致数据库层的压力激增。 

一个简单的雪崩过程:

  1. Redis 集群产生了大面积故障;

  2. 缓存失败,此时仍有大量请求去访问 Redis 缓存服务器;

  3. 在大量 Redis 请求失败后,这些请求将会去访问数据库;

  4. 由于应用的设计依赖于数据库和 Redis 服务,很快就会造成服务器集群的雪崩,最终导致整个系统的瘫痪。

 产生的原因:

1)缓存中有大量数据同时过期,导致大量请求无法得到处理。

2)Redis 缓存实例发生故障宕机了

解决方案: 

  • 【事前】高可用缓存:高可用缓存是防止出现整个缓存故障。即使个别节点,机器甚至机房都关闭,系统仍然可以提供服务,Redis 哨兵(Sentinel) 和 Redis 集群(Cluster) 都可以做到高可用;

  • 【事中】缓存降级(临时支持):当访问次数急剧增加导致服务出现问题时,我们如何确保服务仍然可用。在国内使用比较多的是 Hystrix,它通过熔断、降级、限流三个手段来降低雪崩发生后的损失。只要确保数据库不死,系统总可以响应请求,每年的春节 12306 我们不都是这么过来的吗?只要还可以响应起码还有抢到票的机会;

  • 【事后】Redis备份和快速预热:Redis数据备份和恢复、快速缓存预热。

(2)redis 击穿

 缓存击穿是指当前热点数据存储到期时,多个线程同时并发访问热点数据。因为缓存刚过期,所有并发请求都会到数据库中查询数据。

解决方法:

  • 将热点数据设置为永不过期;

  • 加互斥锁:互斥锁可以控制查询数据库的线程访问,但这种方案会导致系统的吞吐量下降,需要根据实际情况使用。

 (3)缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起id为-1的数据或者特别大的不存在的数据。有可能是黑客利用漏洞攻击从而去压垮应用的数据库。 

  • 验证拦截:接口层进行校验,如鉴定用户权限,对ID之类的字段做基础的校验,如id<=0的字段直接拦截;
  • 缓存空数据:当数据库查询到的数据为空时,也将这条数据进行缓存,但缓存的有效性设置得要较短,以免影响正常数据的缓存;
  •  使用布隆过滤器:布隆过滤器是一种比较独特数据结构,有一定的误差。当它指定一个数据存在时,它不一定存在,但是当它指定一个数据不存在时,那么它一定是不存在的。

二、redis的高可用的概念

在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。

高可用的计算公式是1-(宕机时间)/(宕机时间+运行时间)有点类似与网络传输的参数误码率,我们用9的个数表示可用性:

2个9:99%,一年内宕机时长:1%×365天=3.6524天=87.6h

4个9:99.99%,一年内宕机时长:0.01%×365天=52.56min

5个9:99.999%,一年内宕机时长:0.001%*365天=5.265min

11个9:几乎一年宕机时间只有几秒钟

但是在Redis语境中,高可用的含义似乎要宽泛一些,除了保证提供正常服务(如主从分离、快速容灾技术),还需要考虑数据容量的扩展、数据安全不会丢失等

2.1Redis的高可用技术

在Redis中,实现高可用的技术主要包括持久化、主从复制、哨兵和cluster集群,下面分别说明它们的作用,以及解决了什么样的问题。

  • 持久化: 持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。

  • 主从复制: 主从复制是高可用Redis的基础,哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份(和同步),以及对于读操作的负载均衡和简单的故障恢复。

    • 缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
  • 哨兵: 在主从复制的基础上,哨兵实现了自动化的故障恢复。(主挂了,找一个从成为新的主,哨兵节点进行监控)

    • 缺陷:写操作无法负载均衡;存储能力受到单机的限制。
  • Cluster集群: 通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。(6台起步,成双成对,3主3从)

三、redis主从复制

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

3.1主从复制的作用

  • 据冗余: 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  • 故障恢复: 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  • 负载均衡: 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
  • 高可用基石: 除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

3.2主从复制流程

1)若启动一个slave机器进程,则它会向Master机器发送一个sync command命令,请求同步连接。

(2)无论是第一次连接还是重新、【】连接,Master机器都会启动一个后台进程,将数据快照保存到数据文件中(执行rdb操作),同时Master还会记录修改数据的所有命令并缓存在数据文件中.

(3)后台进程完成缓存操作之后,Master机器就会向slave机器发送数据文件,slave端机器将数据文件保存到硬盘上,然后将其加载到内存中,接着Master机器就会将修改数据的所有操作一并发送给slave端机器。若slave出现故障导致宕机,则恢复正常后会自动重新连接。

(4)Master机器收到slave端机器的连接后,将其完整的数据文件发送给slave端机器,如果Mater同时收到多个slave发来的同步请求,则Master会在后台启动一个进程以保存数据文件,然后将其发送给所有的slave端机器,确保所有的slave端机器都正常。

四、redis一主二从的部署

实验组件

主从redis的版本号IP地址
masterredis-5.0.7192.168.195.100
slave1redis-5.0.7192.168.195.200
slave2redis-5.0.7192.168.195.101

实验具体步骤 

 实验前准备好三台源码编译安装好的redis虚拟机

步骤一:修改master节点的配置文件 

vim /etc/redis/6379.conf 
 bind 0.0.0.0                      #70行,修改监听地址为0.0.0.0(生产环境中,尤其是多网卡最好填写物理网卡的IP)
 daemonize yes                     #137行,开启守护进程,后台启动 
 logfile /var/log/redis_6379.log   #172行,指定日志文件存放目录
 dir /var/lib/redis/6379           #264行,指定工作目录
 appendonly yes                    #700行,开启AOF持久化功能

/etc/init.d/redis_6379 restart     #重启redis服务

 

步骤二:修改slave节点的配置文件

#修改slave1的配置文件
vim /etc/redis/6379.conf 
 bind 0.0.0.0                        #70行,修改监听地址为0.0.0.0(生产环境中需要填写物理网卡的IP)
 daemonize yes                       #137行,开启守护进程,后台启动
 logfile /var/log/redis_6379.log     #172行,指定日志文件目录
 dir /var/lib/redis/6379             #264行,指定工作目录
 replicaof 192.168.73.105 6379       #288行,指定要同步的Master节点的IP和端口
 appendonly yes                      #700行,修改为yes,开启AOF持久化功能

#将配置文件传给slave2
scp /etc/redis/6379.conf 192.168.73.107:/etc/redis/

/etc/init.d/redis_6379 restart  #重启redis
netstat -natp | grep redis      #查看主从服务器是否已建立连接

实验测试 

master写入数据 

127.0.0.1:6379> keys *
 
127.0.0.1:6379> set name zhangsan
 
127.0.0.1:6379> get name

 从节点查询 没有问题

 五、Redis哨兵模式

主从切换技术的方法是:当服务器宕机后,需要手动一台从机切换为主机,这需要人工干预,不仅费时费力而且还会造成一段时间内服务不可用。为了解决主从复制的缺点,就有了哨兵机制。

 哨兵的核心功能:在主从复制的基础上,哨兵引入了主节点的自动故障转移。

 哨兵模式的组成:

哨兵节点: 哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据。

数据节点: 主节点和从节点都是数据节点。

5.1  哨兵模式的作用 

  • 监控: 哨兵会不断地检查主节点和从节点是否运作正常。
  • 自动故障转移: 当主节点不能正常工作时,哨兵会开始自动故障转移操,它会将失效主节点的其中一个从节点升级为新的主节点,并让其它从节点改为复制新的主节点。
  • 通知(提醒): 哨兵可以将故障转移的结果发送给客户端。

此外:哨兵节点也可以是单独独立在其他的主机上,并不需要一定安装redis主从复制的节点服务器上 、

5.2故障转移机制

1、由哨兵节点定期监控发现主节点是否出现了故障

每个哨兵节点每隔1秒会问主节点、从节点及其它哨兵节点发送一次ping命令做一次心检测。如果主节点在一定时间范围内不回复或者是回复一个错误消息,那么这个哨兵就会认为这个主节点主观下线了(单方面的)。当超过半数哨兵节点认为该主节点主观下线了,这样就客观下线了。

2、当主节点出现故障,此时哨兵节点会通过Raft算法(选举算法)实现选举机制共同选举出一个哨兵节点为leader,来负责处理主节点的故障转移和通知。所以整个运行哨兵的集群的数量不得少于3个节点。

3、由leader哨兵节点执行故障转移,过程如下:

  • 将某一个从节点升级为新的主节点,让其它从节点指向新的主节点;
  • 若原主节点恢复也变成从节点,并指向新的主节点;
  • 通知客户端主节点已经更换。

需要特别注意的是,客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作

 5.3哨兵模式中主节点的选拔 

1.过滤掉不健康的(己下线的),没有回复哨兵ping响应的从节点。

2.选择配置文件中从节点优先级配置最高的。(replica-priority,默认值为100)

3.选择复制偏移量最大,也就是复制最完整的从节点。

哨兵的启动依赖于主从模式,所以须把主从模式安装好的情况下再去做哨兵模式。

六、redis哨兵模式的部署(哨兵节点可以单独配置或者放在数据节点一起配置)

主从redis的版本号IP地址哨兵点
masterredis-5.0.7192.168.195.100Sentinel 1
slave1redis-5.0.7192.168.195.200Sentinel 2
slave2redis-5.0.7192.168.195.101Sentinel 3

实验具体操作步骤 

 在redis主从复制的基础上进行哨兵模式的部署

步骤一:修改哨兵节点的配置文件

哨兵的的配置文件是redis软件中自带的配置 

vim /opt/redis-5.0.7/sentinel.conf
......
protected-mode no                #17行,取消注释,关闭保护模式
port 26379                       #21行,Redis哨兵默认的监听端口
daemonize yes                    #26行,指定sentinel为后台启动
logfile "/var/log/sentinel.log"  #36行,指定日志文件存放路径
dir "/var/lib/redis/6379"        #65行,指定数据库存放路径
sentinel monitor mymaster 192.168.195.100 6379 2  #84行,修改
#指定该哨兵节点监控192.168.195.100:6379这个主节点,该主节点的名称是mymaster。
#最后的2的含义与主节点的故障判定有关:至少需要2个哨兵节点同意,才能判定主节点故障并进行故障转移

sentinel down-after-milliseconds mymaster 3000  #113行,判定服务器down掉的时间周期,默认30000毫秒(30秒)
sentinel failover-timeout mymaster 180000  #146行,同一个sentinel对同一个master两次failover之间的间隔时间(180秒)

#传给两外2个哨兵节点
scp /opt/redis-5.0.7/sentinel.conf  192.168.195.200:/opt/redis-5.0.7/
scp /opt/redis-5.0.7/sentinel.conf  192.168.195.100:/opt/redis-5.0.7/

步骤二:启动 哨兵模式,查看其监控状态

#启动三台哨兵
cd /opt/redis-5.0.7/
redis-sentinel sentinel.conf &
 
#在哨兵节点查看监控状态
[root@localhost ~]# redis-cli -p 26379 info Sentinel

实验测试 

 故障模拟

#在Master 上查看redis-server进程号:
[root@localhost ~]# ps -ef | grep redis

#杀死 Master 节点上redis-server的进程号
[root@localhost ~]# kill -9 pid号      #Master节点上redis-server的进程号
[root@localhost ~]# netstat -natp | grep redis

实验结果

 [root@localhost redis-5.0.7]# tail -f /var/log/sentinel.log
 
 
#新master进行键值对的创建
[root@localhost redis-5.0.7]# redis-cli 
127.0.0.1:6379> set newname lisi
OK
127.0.0.1:6379> get newname
"lisi"
127.0.0.1:6379> 

 七 Redis集群模式

集群,即Redis Cluster,是Redis3.0开始引入的分布式存储方案。

集群由多个节点(Node)组成,Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护;从节点只进行主节点数据和状态信息的复制。

7.1集群的作用

(1)数据分区: 数据分区(或称数据分片)是集群最核心的功能。

  • 集群将数据分散到多个节点,一方面突破了Redis单机内存大小的限制,存储容量大大增加;另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。
  • Redis单机内存大小受限问题,在介绍持久化和主从复制时都有提及;例如,如果单机内存太大,bgsave和bgrewriteaof的fork操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出。

(2)高可用: 集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务。

 通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。

7.2Redis集群的数据分片

Redis集群引入了哈希槽的概念。

Redis集群有16384个哈希槽(编号0-16383)。

集群的每个节点负责一部分哈希槽。

每个Key通过CRC16校验后对16384取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。

以3个节点组成的集群为例:

  • 节点A包含0到5460号哈希槽
  • 节点B包含5461到10922号哈希槽
  • 节点c包含10923到16383号哈希   槽

redis集群的部署

真实生产环境中,redis的cluster集群至少需要六台服务器才能实现 ,如果因为电脑性能问题

可以尝试redis多实例部署

实验组件的部署 

安装包:redis-5.0.7.tar.gz

192.168.195.100   我们就用一台机器来搭建

cd /etc/redis/
mkdir -p redis-cluster/redis600{1..6}   #创建redis集群的工作目录、和每个节点的工作目录
ls -R redis-cluster/

到软件包目录,把redis配置文件分别复制到我们第二步所创建的每个节点目录中。也要把/opt/redis-5.0.7/src下的客户端工具redis-cli和服务端命令redis-server复制到每个节点的目录中

cd /opt/redis-5.0.7/src/
ls
cd /opt/redis-5.0.7/
for i in {1..6}; do cp /opt/redis-5.0.7/redis.conf /etc/redis/redis-cluster/redis600$i; cp /opt/redis-5.0.7/src/redis-server /opt/redis-5.0.7/src/redis-cli /etc/redis/redis-cluster/redis600$i; done      
#使用for循环复制可以节省很多时间
cd /etc/redis/redis-cluster/
ls -R
 

修改每个节点目录中的redis配置文件

cd redis6001
vim redis.conf
 
#bind 127.0.0.1     ##第69行;注释掉监听地址,表示监听任意地址(也可设置为0.0.0.0)
protected-mode no    #修改第88行,关闭保护模式,设置为no
port 6001           #修改第92行,修改监听端口为6001
daemonize yes       #修改第136行,开启后台运行
appendonly yes      #修改第699行,开启AOF持久化
 
 
#集群模式配置
cluster-enabled yes    #第832行取消注释,开启集群模式
cluster-config-file nodes-6001.conf   #第840行,每个集群配置文件,取消注释、修改对应的端口(每个节点都要设置对应的)
cluster-node-timeout 15000   #第846行,集群节点之间通信的超时时间;取消注释

启动redis服务,一定要先进入每个节点目录中去使用redis-server命令启动


cd ../redis6001
ls
for i in {1..6}; do cd /etc/redis/redis-cluster/redis600$i; ./redis-server redis.conf; done
ps -elf |grep redis
redis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1                                 #把节点加入到集群当中
--cluster-replicas    指定每个主节点有多少个从节点做主从复制
 
 
redis-cli -p 6001    #登录redis数据库
cluster slots        #查看主从对应关系

 

验证,键的插入

redis-cli -p 6001 -c    
-c  实现节点间的跳转,如果不加会报错
set name hj

  登录到6004节点

redis-cli -p 6004 -c
keys *
get name

Redis集群拓展:

数据量过多如何处理?

当数据量过多的情况下,一种简单的方式是升级Redis实例的资源配置,包括增加内存容量、磁盘容量、更好配置的CPU等,但这种情况下Redis使用RDB进行持久化的时候响应会变慢,Redis通过fork子进程来完成数据持久化,但fork在执行时会阻塞主线程,数据量越大,fork的阻塞时间就越长,从而导致Redis响应变慢。

Redis的切片集群可以解决这个问题,也就是启动多个Redis实例来组成一个集群,再按照一定的规则把数据划分为多份,每一份用一个实例来保存,这样客户端只需要访问对应的实例就可以获取数据。在这种情况下fork子进程一般不会给主线程带来较长时间的阻塞,如下图:

切片集群架构图
将20GB的数据分为4分,每份包含5GB数据,客户端只需要找到对应的实例就可以获取数据,从而减少主线程阻塞的时间。

当数据量过多的时候,可以通过升级Redis实例的资源配置或者通过切片集群的方式。前者实现起来简单粗暴,但这数据量增加的时候,需要的内存也在不断增加,主线程fork子进程就有可能会阻塞,而且该方案受到硬件和成本的限制。相比之下第二种方案是一种扩展性更好的方案,如果想保存更多的数据,仅需要增加Redis实例的个数,不用担心单个实例的硬件和成本限制。在面向百万、千万级别的用户规模时,横向扩展的 Redis 切片集群会是一个非常好的选择。

选择切片集群也是需要解决一些问题的:

  • 数据切片后,在多个实例之间怎么分布?
  • 客户端怎么确定想要访问的实例是哪一个?

Redis采用了Redis Cluster的方案来实现切片集群,具体的Redis Cluster采用了哈希槽(Hash Slot)来处理数据和实例之间的映射关系。在Redis Cluster中,一个切片集群共有16384个哈希槽(为什么Hash Slot的个数是16384),这些哈希槽类似于数据的分区,每个键值对都会根据自己的key被影射到一个哈希槽中,映射步骤如下:

  • 根据键值对key,按照CRC16算法计算一个16bit的值。
  • 用计算的值对16384取模,得到0~16383范围内的模数,每个模数对应一个哈希槽。

这时候可以得到一个key对应的哈希槽了,哈希槽又是如何找到对应的实例的呢?

在部署Redis Cluster的时候,可以通过cluster create命令创建集群,此时Redis会自动把这些槽分布在集群实例上,例如一共有N个实例,那么每个实例包含的槽个数就为16384/N。当然可能存在Redis实例中内存大小配置不一的问题,内存大的实例具有更大的容量。这种情况下可以通过cluster addslots命令手动分配哈希槽。

redis-cli -h 33.33.33.3 –p 6379 cluster addslots 0,1redis-cli -h 33.33.33.4 –p 6379 cluster addslots 2,3redis-cli -h 33.33.33.5 –p 6379 cluster addslots 4
复制代码
复制代码

要注意的是,如果采用cluster addslots的方式手动分配哈希槽,需要将16384个槽全部分配完,否则Redis集群无法正常工作。现在通过哈希槽,切片集群就实现了数据到哈希槽、哈希槽到实例的对应关系,那么客户端如何确定需要访问的实例是哪一个呢?

(二)客户端定位集群中的数据

客户端请求的key可以通过CRC16算法计算得到,但客户端还需要知道哈希槽分布在哪个实例上。在最开始客户端和集群实例建立连接后,实例就会把哈希槽的分配信息发给客户端,实例之间会把自己的哈希槽信息发给和它相连的实例,完成哈希槽的扩散。这样客户端访问任何一个实例的时候,都能获取所有的哈希槽信息。当客户端收到哈希槽的信息后会把哈希槽对应的信息缓存在本地,当客户端发送请求的时候,会先找到key对应的哈希槽,然后就可以给对应的实例发送请求了。

但是,哈希槽和实例的对应关系不是一成不变的,可能会存在新增或者删除的情况,这时候就需要重新分配哈希槽;也可能为了负载均衡,Redis需要把所有的实例重新分布。

虽然实例之间可以互相传递消息以获取最新的哈希槽分配信息,但是客户端无法感知这个变化,就会导致客户端访问的实例可能不是自己所需要的了。

Redis Cluster提供了重定向的机制,当客户端给实例发送数据读写操作的时候,如果这个实例上没有找到对应的数据,此时这个实例就会给客户端返回MOVED命令的相应结果,这个结果中包含了新实例的访问地址,此时客户端需要再给新实例发送操作命令以进行读写操作,MOVED命令如下:

GET hello:key(error) MOVED  33.33.33.33:6379
复制代码
复制代码

返回的信息代表客户端请求的key所在的哈希槽为3333,实际是在33.33.33.33这个实例上,此时客户端只需要向33.33.33.33这个实例发送请求就可以了。

此时也存在一个小问题,哈希槽中对应的数据过多,导致还没有迁移到其他实例,此时客户端就发起了请求,在这种情况下,客户端就对实例发起了请求,如果数据还在对应的实例中,会给客户端返回数据;如果请求的数据已经被转移到其他实例上,客户端就会收到实例返回的ASK命令,该命令表示:哈希槽中数据还在前一种、ASK命令把客户端需要访问的新实例返回了。此时客户端需要给新实例发送ASKING命令以进行请求操作。

值得注意的是ASK信息和MOVED信息不一样,ASK信息并不会更新客户端本地的缓存的哈希槽分配信息,也就是说如果客户端再次访问该哈希槽还是会请求之前的实例,直到数据迁移完成.


                

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/8809.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新手零基础自学Python,安装并配置环境+教程

第一步&#xff1a;搭建python运行环境 在 Windows 上安装 Python 和安装普通软件一样简单&#xff0c;下载安装包以后猛击“下一步”即可。 Python 安装包下载地址&#xff1a;https://www.python.org/downloads/ 打开该链接&#xff0c;可以看到有两个版本的 Python&#…

java框架 —— Spring

Spring[TOC](Spring)1、概述1.1、优点1.2、组成2. IOC概述2.1 什么是IOC2.1.1 推导过程2.1.2 IOC本质2.2 HelloSpring2.2.1 导入Jar包2.2.2 编写代码2.2.2 思考2.3 IOC过程2.4 IOC 接口3. Bean 管理3.1 基于xml方式——set方法注入3.2 FactoryBean3.3 bean 作用域3.4 bean 生命…

Java——面向对象进阶(封装、继承、多态)

Java面向对象三大特性——封装、继承、多态一、封装1.封装基本概念2.访问修饰符3.Java中封装的理解4.封装的优点二、继承1.为什么需要继承2.继承层次结构3.super和this关键字4.继承语法与设计一个继承体系三、多态1.多态的概念2.多态的实现条件3.多态的优缺点一、封装 1.封装基…

【微服务架构组件】Nacos

初识nacos 最近在整合nacos做配置的热下发&#xff0c;总结下。 Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称&#xff0c;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 阿里开源产品&#xff1a;什么是 Nacos 如 Na…

[Leetcode]138. 复制带随机指针的链表

目录 1.题目链接 2.1解法①(暴力) 2.1.1解法思路&#xff1a; 2.1.2代码实现&#xff1a; 2.2解法②(进阶) 2.1.1解法思路&#xff1a; 2.2.2代码实现&#xff1a; 1.题目链接 138. 复制带随机指针的链表 - 力扣&#xff08;LeetCode&#xff09; 2.1解法①(暴力) 2.1.…

软考 - 操作系统

操作系统概述 bit和byte区别 bit 位 说白了就是0或者1&#xff1b;计算机内存中的存储都是01这两个东西。 byte(B) 字节 1byte8bit&#xff08;一字节 8比特&#xff09; 1byte就是1B 1byte 存1个英文字母&#xff0c;2个byte存一个汉字。 了解 操作系统的作用&#xff1…

SpringBoot使用EasyExcel类一键导出数据库数据生成Excel,导入Excle生成List<>数据(作者直接给demo项目)

文章目录一、简单一键导出Excel直接给出生成效果Empty&#xff0c;这个很关键controller层EasyExcel类的多种使用方式二、导入Excel生成List<>数据controller层&#xff0c;简单写法监听器写法&#xff08;观察者模式&#xff09;&#xff0c;稍微麻烦其他如果要使类中的…

动态拼接 merge 语句

【问题】 Hello everyone, I have one query, would be great if anyone can help me out on this. In SQL, I have two tables with same column names. Want to query if there is any difference in the column values and if yes will update the values(in the first ta…

LEADTOOLS 入门教程: 使用 AWS Lambda 转换文档 - C# .NET Core

LEADTOOLS 是一个综合工具包的集合&#xff0c;用于将识别、文档、医疗、成像和多媒体技术整合到桌面、服务器、平板电脑、网络和移动解决方案中&#xff0c;是一项企业级文档自动化解决方案&#xff0c;有捕捉&#xff0c;OCR&#xff0c;OMR&#xff0c;表单识别和处理&#…

SSM框架真没那么难,这份阿里大佬的进阶实战笔记真给讲透了!

SSM框架&#xff1a; SSM框架是spring MVC &#xff0c;spring和mybatis框架的整合&#xff0c;是标准的MVC模式&#xff0c;将整个系统划分为表现层&#xff0c;controller层&#xff0c;service层&#xff0c;DAO层四层 使用spring MVC负责请求的转发和视图管理 spring实现…

Docker学习笔记

1.docker比vm快的原因: docker有着比虚拟机更少的抽象层,不需要实现硬件资源的虚拟化运行,运行在docker上的程序使用的都是物理机的资源. dicker利用的是宿主机的内核,不需要加载操作系统的os内核. 2.docker帮助文档docker help 具体到某一个命令是使用 docker run --help即可…

【JMeter】Jmeter分布式压测教程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录一、原理二、环境搭建2.1 环境准备2.2 slave机器配置2.3 master机器配置三、脚本及执行3.1 参数化问题3.2 GUI启动测试3.3 命令行启动测试总结一、原理 Jmeter分布式…

【深入理解Kotlin协程】CoroutineScope.launch源码追踪扒皮

lifecycleScope、viewModelScope、GlobalScope、MainScope的上下文 协程最重要的就是协程上下文对象&#xff0c;因为通过上下文可以获取到协程相关的任何东西(Job、Dispatcher、Interceptor、Name、ExceptionHandler)&#xff0c;所以有必要了解清楚常用的协程作用域对象中cor…

asp.net+sqlserver汽车4s店销售网站系统c#项目

数据项 管理员信息表&#xff5b;用户编号&#xff0c;用户名称&#xff0c;用户密码&#xff5d; 新闻信息表&#xff5b;编号&#xff0c;标题&#xff0c;内容&#xff0c;添加时间&#xff5d; 汽车信息表&#xff5b;编号&#xff0c;汽车名称&#xff0c;汽车价格&#x…

制造业行业现状及智能生产管理系统一体化解决方案

前言&#xff1a; 《中国制造2025》作为我国实施制造强国战略第一个十年的行动纲领。它重点提出了坚持&#xff1a;创新驱动、质量为先、绿色发展、结构优化、人才为本的基本方针。坚持&#xff1a;市场主导、政策引导&#xff0c;立足当前、着眼长远&#xff0c;整体推进、重…

Selenium实现原理

Selenium 是目前主流的用于Web应用程序测试的工具&#xff0c;可以直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。 selenium的实现原理是这样的&#xff1a; 1.运行代码&#xff0c;启动浏览器后&#xff0c;webdriver会将浏览器绑定到特定端口&#xff0c;作为we…

[go学习笔记.第十五章.反射] 1.反射的基本介绍以及实践

一.反射的引入以及基本介绍 1.看两个问题 (1).对于结构体的序列化和反序列化&#xff0c;看一段代码 package mainimport("fmt" "encoding/josn" )type Monster struct {Name string json:"monsterName"Age int json:"monsterAge&quo…

deque容器(20221115)

1、基本概念 功能&#xff1a;双端数组&#xff0c;可以对头端进行插入删除元素 deque与vector的区别&#xff1a; vector对应头部的插入删除效率低&#xff0c;数据量越大&#xff0c;效率越低 deque对头部的插入删除速度比vector快 vector访问元素速度比deque快 deque内…

sanic 教程

sanic 教程 在Sanic的生命周期流程大致如下&#xff1a; http请求——Sanic解析request——匹配路由——请求中间件——视图函数——响应中间件——http响应 依赖库 sanic21.3.4 sanic-jwt1.7.0 sanic-openapi21.12.0 gunicorn20.1.0 PyMySQL1.0.2 aiomysql0.1.1 DBUtils1.3…

WPS(WSC)中M1 到M8 图解

背景 之前实习的时候就学了Wifi p2p相关的东西&#xff0c;当时找M1到M8的功能把我累惨了&#xff0c;找到的还全是千篇一律的东西&#xff0c;讲的不是很清楚&#xff08;当然原版出书的那个前辈肯定是懂的&#xff09;&#xff0c;但是对我等小白不友好&#xff0c;就萌生了这…