Redis性能压测脚本介绍

Redis的所有数据是保存在内存当中的, 得益于内存⾼效的读写性能, Redis的性能是⾮常强悍 。但 是,内存的缺点是断电即丢失,所以 ,在实际项⽬中, Redis—旦需要保存—些重要的数据, 就不可能完全使⽤内存保存数据 。因此, 在真实项⽬中要使⽤Redis —定需要针对应⽤场景, Redis的性 能进⾏估算, 从⽽在数据安全性与读写性能之间找到—个平衡点。

Redis提供了压测脚本redis-benchmark 可以对Redis进⾏快速的基准测试。

# 20个线程,100W个请求,测试redis的set指令(写数据)
redis-benchmark -a 123qweasd -t set -n 1000000 -c 20

redis-benchmark更多参数, 使⽤ redis-benchmark --help指令查看

关键结果解析:
吞吐量(throughput):平均每秒处理约11.6万次写操作(116536.53 requests per second)。
延迟(latency):

  •         avg(平均延迟):0.111毫秒。
  •         p50(中位数延迟):0.111毫秒。
  •         p95(95%请求延迟):0.167毫秒。
  •         max(最大延迟):3.199毫秒。

操作建议:

  • 更多参数可通过redis-benchmark --help查看。
  • 调整Redis部署架构后,建议多次进行对比测试以评估性能变化。

 Redis数据持久化机制详解 

1 、整体介绍Redis的数据持久化机制

官⽹介绍地址: Redis persistence | Docs

Redis提供了很多跟数据持久化相关的配置, ⼤体上, 可以组成以下⼏种策略:

. ⽆持久化: 完全关闭数据持久化, 不保证数据安全 。相当于将Redis完全当做缓存来⽤ .  RDB(RedisDatabase) :按照—定的时间间隔缓存Redis所有数据快照。

 AOF(Append Only File) :记录Redis收到的每—次写操作 。这样可以通过操作重演的⽅式恢复 Redis的数据

RDB+AOF 同时保存Redis的数据和操作。

两种⽅式的优缺点:

(1)RDB

 优点:

1 RDB⽂件⾮常紧凑, ⾮常适合定期备份数据。

2 RDB快照⾮常适合灾难恢复。

3 RDB备份时性能⾮常快, 对主线程的性能⼏乎没有影响 RDB备份时, 主线程只需要启  动—个负责数据备份的⼦线程即可 。所有的备份⼯作都由⼦线程完成, 这对主线程的IO性能 ⼏乎没有影响。

4 )与AOF相⽐, RDB在进⾏⼤数据量重启时会快很多。

 缺点:

1 RDB不能对数据进⾏实时备份, 所以, 总会有数据丢失的可能。

2 RDB需要fork化⼦线程的数据写⼊情况, fork的过程中, 需要将内存中的数据克隆—  。如果数据量太⼤, 或者CPU性能不是很好, RDB⽅式就容易造成Redis短暂的服务停 。相⽐之下, AOF也需要进⾏持久化, 但频率较低 并且你可以调整⽇志重写的频率

 (2) AOF

优点:

1 )AOF持久化更安全 。例如Redis默认每秒进⾏—次AOF写⼊, 这样, 即使服务崩溃, 最多损失—秒的操作。

2)AOF的记录⽅式是在之前基础上每次追加新的操作 。因此AOF不会出现记录不完整的情  。即使因为—些特殊原因, 造成—个操作没有记录完整, 也可以使⽤ redis-check-aof 具轻松恢复。

3 )当AOF⽂件太⼤时, Redis会⾃动切换新的⽇志⽂件 。这样就可以防⽌单个⽂件太⼤的 问题。

4 )AOF记录操作的⽅式⾮常简单易懂, 你可以很轻松的⾃⾏调整⽇志 。⽐如, 如果你错误 的执⾏了—次 FLUSHALL 操作, 将数据误删除了 。使⽤AOF 你可以简单的将⽇志中最后 —条FLUSHALL指令删掉, 然后重启数据库, 就可以恢复所有数据。

  缺点:

1 )针对同样的数据集, AOF⽂件通常⽐RDB⽂件更⼤ 

2)在写操作频繁的情况下, AOF备份的性能通常⽐RDB更慢。

整体使⽤建议:

1 )如果你只是把Redis 当做—个缓存来⽤, 可以直接关闭持久化

2 )如果你更关注数据安全性, 并且可以接受服务异常宕机时的⼩部分数据损失, 那么可以简单的使 RDB策略 。这样性能是⽐较⾼的。

3 )不建议单独使⽤AOF RDB配合AOF 可以让数据恢复的过程更快。

2 RDB详解

(1) RDB能⼲什么

RDB可以在指定的时间间隔, 备份当前时间点的内存中的全部数据集, 并保存到餐盘⽂件当中 。通常 dump.rdb⽂件 。在恢复时, 再将磁盘中的快照⽂件直接都会到内存⾥ 

由于RDB存的是全量数据, 你甚⾄可以直接⽤RDB来传递数据 。例如如果需要从—个Redis服务中将 数据同步到另—个Redis服务(最好是同版本) 就可以直接复制最近的RDB⽂件。

(2)相关重要配置

1save策略: 核⼼配置

# 保存策略:<秒数> <写操作次数>,满足条件触发快照
save 3600 1    # 1小时内至少1次写操作
save 300 100   # 5分钟内至少100次写操作
save 60 10000  # 1分钟内至少10000次写操作dir /data/redis        # 快照存储目录
dbfilename dump.rdb    # 快照文件名
rdbcompression yes     # 是否压缩(默认开启,可节省磁盘空间但消耗CPU)
stop-writes-on-bgsave-error yes  # 快照失败时是否停止写入(默认开启,保证数据一致性)

2 dir ⽂件⽬录

3 dbfilename ⽂件名 默认dump.rdb

4 rdbcompression 是否启⽤RDB压缩, 默认yes 。 如果不想消耗CPU进⾏压缩, 可以设置为no

5 stop-writes-oin-bgsave-error 默认yes 。如果配置成no 表示你不在乎数据不—致或者有其他 的⼿段发现和控制这种不—致 。在快照写⼊失败时, 也能确保redis继续接受新的写⼊请求。

6rdbchecksum 默认yes 。在存储快照后, 还可以让redis使⽤CRC64算法来进⾏数据校验, 但是这 样做会增加⼤约10%的性能消耗 。如果希望获得最⼤的性能提升, 可以关闭此功能。

(3)何时会触发RDB备份

1 到达配置⽂件中默认的快照配置时, 会⾃动触发RDB快照

2⼿动执⾏save或者bgsave指令时, 会触发RDB快照 。 其中save⽅法会在备份期间阻塞主线程   bgsve则不会阻塞主线程 。但是他会fork—个⼦线程进⾏持久化, 这个过程中会要将数据复制—份, 因此会占⽤更多内存和CPU

3 主从复制时会触发RDB备份。

LASTSAVE指令查看最后—次成功执⾏快照的时间 。时间是—个代表毫秒的LONG数字, linux中可 以使⽤date -d @{timestamp} 快速格式化。

3 AOF详解

(1)AOF能⼲什么

以⽇志的形式记录每个写操作(读操作不记录) 。只允许追加⽂件⽽不允许改写⽂件。

(2)相关重要配置

1 )appendonly 是否开启aof 。 默认是不开启的。

2)appendfilename ⽂件名称。

appendfilename "appendonly.aof"

Redis7中, 对⽂件名称做了调整 。原本只是—个⽂件, 现在换成了三个⽂件 base.rdb⽂件即⼆进  制的数据⽂件 incr.aof是增量的操作⽇志 manifest则是记录⽂件信息的元⽂件 。其实在Redis7 前的版本中, aof⽂件也会包含⼆进制的RDB部分和⽂本的AOF部分 。在Redis7中, 将这两部分分成 了单独的⽂件, 这样, 即可以分别⽤来恢复⽂件, 也便于控制AOF⽂件的⼤⼩ 

从这⼏个⽂件中能够看到, 现在的AOF已经具备了RDB+AOF的功能 。并且, 拆分增量⽂件的⽅式, 也能够进—步控制aof⽂件的⼤⼩ 

3)appendfsync 同步⽅式 。默认everysecond 每秒记录—次 no 不记录(交由操作系统进⾏内存刷 ) always 记录每次操作, 数据更安全, 但性能较低。

4) appenddirname AOF⽂件⽬录 。新增参数, 指定aof⽇志的⽂件⽬录 。 实际⽬录是 {dir}+ {appenddirname}

5) auto-aof-rewrite-percentage, auto-aof-rewrite-min-size ⽂件重写触发策略 。默认每个⽂件 64M 写到100% 进⾏—次重写。

Redis会定期对AOF中的操作进⾏优化重写, AOF中的操作更为精简 。例如将多个INCR指令, 合并成—个SET指令 。同时, Redis7AOF⽂件中, 会⽣成新的base rdb⽂件和incr.aof件。

AOF重写也可以通过指令 BGREWRITEAOF ⼿动触发

6)no-appendfsync-on-rewrite aof重写期间是否同步

(3)AOF⽂件内容解析

示例:打开aof配置, aof⽇志⽂件appendonly.aof 。然后使⽤ redis-cli连接redis服务, 简单执⾏两个 set操作。

[root@192-168-65-214 my redis]# redis-cli -a 123qweasd
Warning: Using a password with '-a ' or '-u ' option on the command line interface
may not be safe.
127.0.0.1:6379> keys * (empty array)
127.0.0.1:6379> set k1 v1 OK
127.0.0.1:6379> set k2 v2 OK

 然后, 就可以打开appendonly.aof.1.incr.aof增量⽂件 。⾥⾯其实就是按照Redis的协议记录了每—次操作。

这就是redis的指令协议 redis就是通过TCP协议, —次次解析各个指 。⽐如—个set k1 v1 这样的 指令, *3表示由三个部分组成, 第—个部分 $3 set 表示三个字符⻓度的set组成第—个部分。

了解这个协议后, 你甚⾄可以很轻松的⾃⼰写—个Redis的客户 。例如:

package com.roy.redis;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;/**
* Author:  roy
* Description:
**/
public class MyRedisClient {OutputStream write;
InputStream reader;public MyRedisClient(String host,int port) throws IOException {
Socket socket = new Socket(host,port);
write = socket.getOutputStream();
reader = socket.getInputStream();}
//auth 123qweasd
public String auth(String password){
//1 组装报⽂
StringBuffer command = new StringBuffer();
command.append("*2").append("\r\n");//参数数量
command.append("$4").append("\r\n");//第—个参数⻓度
command.append("AUTH").append("\r\n");//第—个参数值
//socket编程需要关注⼆进制⻓度。
command.append("$").append(password.getBytes().length).append("\r\n");//第 ⼆个参数⻓度
command.append(password).append("\r\n");//第⼆个参数值
//2 发送报⽂到
try {
write.write(command.toString().getBytes());
//3 接收redis响应
byte [] response = new byte [1024];
reader.read(response);
return new String(response);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//set k4 v4
public String set(String key, String value){
//1 组装报⽂
StringBuffer command = new StringBuffer();
command.append("*3").append("\r\n");//参数数量
command.append("$3").append("\r\n");//第—个参数⻓度
command.append("SET").append("\r\n");//第—个参数值
//socket编程需要关注⼆进制⻓度。
command.append("$").append(key.getBytes().length).append("\r\n");//第⼆个参数⻓度
command.append(key).append("\r\n");//第⼆个参数值
command.append("$").append(value.getBytes().length).append("\r\n");//第三 个参数⻓度
command.append(value).append("\r\n");//第三个参数值
//2 发送报⽂到
try {
write.write(command.toString().getBytes());
//3 接收redis响应
byte [] response = new byte [1024];
reader.read(response);
return new String(response);
} catch (IOException e) {
throw new RuntimeException(e);
}
}public static void main(String [] args) throws IOException {
MyRedisClient client = new MyRedisClient("192.168.65.214",6379);
System.out.println(client.auth("123qweasd"));
System.out.println(client.set("test","test"));
}
}

(4)AOF⽇志恢复

如果Redis服务出现—些意外情况, 就会造成AOF⽇志中指令记录不完整 。例如, ⼿动编辑

appendonly.aof.1.incr.aof⽇志⽂件, 在最后随便输⼊—段⽂字, 就可以模拟指令记录不完整的情  。这时, Redis服务重启, 就会发现重启失败  ⽇志⽂件中会有如下错误⽇志:

21773:M 11 Jun 2024 18:22:43.928 * DB loaded from base file
appendonly.aof.1.base.rdb: 0.019 seconds
21773:M 11 Jun 2024 18:22:43.928 # Bad file format reading the append only file appendonly.aof.1.inc r.aof: make a backup of your AOF file, then use ./redis-
check-aof --fix <filename.manifest>

需要配置⽇志⽂件, 例如: logfile "/root/myredis/logs/6379.log"

这时就需要先将⽇志⽂件修复, 然后才能启动。

[root@192-168-65-214 appendonlydir]# redis-check-aof --fix
appendonly.aof.1.inc r.aof
Start checking Old-Style AOF
AOF appendonly.aof.1.inc r.aof format error
AOF analyzed: filename=appendonly.aof.1.inc r.aof, size=132, ok_up_to=114,
ok_up_to_line=27, diff=18
This will shrink the AOF appendonly.aof.1.inc r.aof from 132 bytes, with 18 bytes,
to 114 bytes
Continue? [y/N]: y
Successfully truncated AOF appendonly.aof.1.inc r.aof

 --修复的过程实际上就是将最后那—条指令删除掉。

注, 对于RDB⽂件, Redis同样提供了修复指令redis-check-rdb 但是, 由于RDB是⼆进制压 缩⽂件, —般不太可能被篡改, 所以—般⽤得并不太多。 

4 、混合持久化策略

RDBAOF两种持久化策略各有优劣, 所以在使⽤Redis时, 是⽀持同时开启两种持久化策略的 。在 redis.conf配置⽂件中, 有—个参数可以同时打开RDBAOF两种持久化策略。

# Redis can create append-only base files in either RDB or AOF formats. Using
# the RDB format is always faster and more efficient, and disabling it is only
# supported for backward compatibility purposes.
aof-use-rdb-preamble yes

这也说明, 如果同时开启RDBAOF两种持久化策略, 那么Redis在恢复数据时, 其实还是会优先选  择从AOF的持久化⽂件开始恢复 。因为通常情况下, AOF的数据集⽐RDB更完整 。⽽且AOF的持久化 策略现在已经明确包含了RDBAOF两种格式, 所以AOF恢复数据的效率也还是⽐较⾼的。

但是要注意, 既然服务重启时只找AOF⽂件, 那是不是就不需要做RDB备份了呢? 通常建议还是增加 RDB备份 。因为AOF数据通常在不断变化, 这样其实不太利于定期做数据备份 。所以通常建议保留RDB⽂件并定期进⾏备份, 作为保证数据安全的后⼿ 

最后要注意, Redis的持久化策略只能保证单机的数据安全 。如果服务器的磁盘坏了, 那么再好的持久化策略也⽆法保证数据安全 。如果希望进—步保证数据安全, 那就需要增加以下⼏种集群化的⽅案了。

三、Redis主从复制Replica机制详解 

接下来的三种Redis分布式优化⽅案, 主从复制 、哨兵集群 Redis集群, 都是在分布式场景下保护 Redis数据安全以及流量分摊的⽅案 。他们是层层递进的。

1 Replica是什么?有什么⽤?

 官⽹介绍 Redis replication | Docs 

redis.conf中的描述

# Master-Replica replication. Use replicaof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication. #
#   +------------------+      +---------------+
#   |      Master      | ---> |    Replica    |
#   | (receive writes) |       |  (exact copy) |
#   +------------------+      +---------------+ #
# 1) Redis replication is asynchronous, but you can configure a master to
#    stop accepting writes if it appears to be not connected with at least
#    a given number of replicas.
# 2) Redis replicas are able to perform a partial resynchronization with the
#    master if the replication link is lost for a relatively small amount of
#    time. You may want to configure the replication backlog size (see the next
#    sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
#    network partition replicas automatically try to reconnect to masters
#    and resynchronize with them.

简单总结: 主从复制 。当Master数据有变化时, ⾃动将新的数据异步同步到其他slave中。

最典型的作⽤ 

  1. .  读写分离: mater以写为主, Slave以读为主 
  2.  .  数据备份+容灾恢复

 2 、如何配置Replica

配置⽅式在基础课程部分有详细讲解, 这⾥不做过多重复 。简单总结—个原则:配从不配主 。 这意味着对于—个Redis服务, 可以在⼏乎没有影响的情况下, 给他配置—个或者多个从节点。

相关核⼼操作简化为以下⼏点:

  REPLICAOF host port|NO ONE : —般配置到redis.conf中。

  SLAVEOF host port|NO ONE 在运⾏期间修改slave节点的信息 。如果该服务已经是某个主库 的从库了, 那么就会停⽌和原master的同步关系。

 3 、如何确定主从状态?从库可以写数据吗?

主从状态可以通过 info replication查看 。例如, 在—个主从复制的master节点上查看到的主从状态是这样的: 

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.65.214,port=6380,state=online,offset=56,lag=1
master_failover_state:no-failover
master_replid:56a1835bdb1f02d2398fac3c34a321e665b07d36
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:56

 重点要观察slavestate状态 。 另外, 可以观察下master_repl_offset参数 。如果是刚建⽴ Replica 数据同步是需要过程的, 这时可以看到offset往后推移的过程。

从节点上查看到的主从状态是这样的: 

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:192.168.65.214
master_port:6379
master_link_status:up
master_last_io_seconds_ago:6
master_sync_in_progress:0
slave_read_repl_offset:574
slave_repl_offset:574
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:56a1835bdb1f02d2398fac3c34a321e665b07d36
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:574
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:560

重点要观察master_link_status

默认情况下, 从库是只读的,不允许写⼊数据 因为数据只能从masterslave同步, 如果slave修改数据, 就会造成数据不—致。 

127.0.0.1:6380> set k4 v4
(error) READONLY You can 't write against a read only replica.

 redis.conf中配置了slave的默认权限

# Since Redis 2.6 by default replicas are read-only.
#
# Note: read only replicas are not designed to be exposed to untrusted clients
# on the internet. It 's just a protection layer against misuse of the instance.
# Still a read only replica exports by default all the administrative commands
# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve
# security of read only replicas using 'rename-command ' to shadow all the
# administrative / dangerous commands.
replica-read-only yes

这⾥也提到, 对于slave从节点, 虽然禁⽌了对数据的写操作, 但是并没有禁⽌CONFIG DEBUG管理指令, 这些指令如果和主节点不—致, 还是容易造成数据不—致 。如果为了安全起见, 可以使⽤ rename-command⽅法屏蔽这些危险的指令。

例如在redis.conf配置⽂件中增加配置 rename-command CONFIG " "  。就可以屏蔽掉slave上的 CONFIG指令。

很多企业在维护Redis时, 都会通过rename 直接禁⽤keys , flushdb, flushall等这—类危险的指 令。 

4 、如果Slave上已经有数据了, 同步时会如何处理?

在从节点的⽇志当中其实能够分析出结果:

 也可以在从节点尝试解除主从关系, 再重新建⽴主从关系测试—下。

 5 、主从复制⼯作流程

(1)Slave启动后, 向master发送—个sync请求 。等待建⽴成功后, slave会删除掉⾃⼰的数据⽇志⽂件, 等待主节点同步。

(2) master接收到slave的sync请求后, 会触发—次RDB全量备份, 同时收集所有接收到的修改数据 的指令 。然后master将RDB和操作指令全量同步给slave 。完成第—次全量同步。

(3)主从关系建⽴后, master会定期向slave发送⼼跳包, 确认slave的状态 。⼼跳发送的间隔通过参 数repl-ping-replica-period指定 。默认10秒。

(4) 只要slave定期向master回复⼼跳请求, master就会持续将后续收集到的修改数据的指令传递给 slave 。同时, master会记录offset, 即已经同步给slave的消息偏移量。

(5)如果slave短暂不回复master的⼼跳请求, master就会停⽌向slave同步数据 。直到slave重新上线 后, master从offset开始, 继续向slave同步数据。

6 、主从复制的缺点

(1) 复制延时,信号衰减: 所有写操作都是先在master上操作, 然后再同步到slave, 
所以数据同步一定会有延迟。当系统繁忙,或者slave数量增加时,这个延迟会更加严重。
(2) master高可用:如果master挂了, slave节点是不会自动切换master的,只能等待人工干预,
重启master服务,或者调整主从关系,将—个slave切换成master,同时将其他slave的主节点调整为新的master。

 后续的哨兵集群, 就相当于做这个人工干预的工作。当检测到master挂了之后, 自动从slave中选择一个节点,切换成master。


(3)从数据安全性的角度, 主从复制牺牲了服务高可用, 但是增加了数据安全。 

四、Redis哨兵集群Sentinel机制详解

1 Sentinel是什么?有什么⽤

官⽹介绍: High availability with Redis Sentinel | Docs

 

RedisSentinel不负责数据读写, 主要就是给RedisReplica主从复制提供⾼可⽤功能 。主要作⽤有四个:

.  主从监控:监控主从Redis运⾏是否正常

.  消息通知:将故障转移的结果发送给客户端

.  故障转移: 如果master异常, 则会进⾏主从切换 。将其中—个slave切换成为master

.  配置中⼼: 客户端通过连接哨兵可以获取当前Redis服务的master地址。

2 Sentinel核⼼配置

Sentinel的环境搭建以及基础使⽤, 在基础版中已经有详细过程 。这⾥不再赘述 。这⾥以单机模拟搭 Sentinel以及主从集群 Redis的服务端⼝为6379(master),6380,6381 Sentinel的服务端⼝为

26379,26380,26381

Sentinel最核⼼的配置其实就是 sentinel.conf中的sentinel monitor <master-name> <ip> <redis- port> <quorum>

这个配置中, 最抽象的参数就最后的那个quorum 这个参数是什么意思呢? 这就需要了解—下 Sentinel的⼯作原理。

3 、解析Sentinel⼯作原理

Sentinel的核⼼⼯作原理分两个步骤, —是如何发现master服务宕机了 。⼆是发现master服务宕机后, 如何切换新的master

(1)如何发现master服务宕机

这⾥有两个概念需要了解, S_DOWN 主观下线) O_DOWN 客观下线)

对于每—Sentinel服务, 他会不断地往master发送⼼跳, 监听master的状态 。如果经过—段时间

(参数sentinel down-after-milliseconds <master-name> <milliseconds> 指定 。默认30秒) 没有 收到master的响应, 他就会主观的认为这个master服务下线了 。也就是S_DOWN

但是主观下线并不—定是master服务的问题, 如果⽹络出现抖动或者阻塞, 也会造成master的响应 超时 。为了防⽌⽹络抖动造成的误判, RedisSentinel就会互相进⾏沟通, 当超过quorum

Sentinel节点都认为master已经出现S_DOWN后, 就会将master标记为O_DOWN 。此时才会真正确 master的服务是宕机的, 然后就可以开始故障切换了。

在配置Sentinel集群时, 通常都会搭建奇数个节点, ⽽将quorum配置为集群中的过半个数 。这样可以最⼤化的保证Sentinel集群的可⽤性。

(2)发现master服务宕机后, 如何切换新的master

当确定master宕机后, Sentinel会主动将—个新的slave切换为mater 。这个过程是怎么做的呢? 通过以下—个Sentinel服务的⽇志, 可以看到整个过程:

从这个⽇志中, 可以看到Sentinel在做故障切换时, 是经过了以下⼏个步骤的:

1)master变成O_DOWN后, Sentinel会在集群中选举产⽣—个服务节点作为Leader Leader将负 责向其他Redis节点发送命令, 协调整个故障切换过程 。在选举过程中, Sentinel是采⽤的Raft法, 这是—种多数派统—的机制, 其基础思想是对集群中的重⼤决议, 只要集群中超过半数的节点投 票同意, 那么这个决议就会成为整个集群的最终决议 。这也是为什么建议Sentinelquorum设置为   集群超半数的原因。

2)Sentinel会在剩余健康的Slave节点中选举出—个节点作为新的Master 。 选举的规则如下:

.  ⾸先检查是否有提前配置的优先节点:各个服务节点的redis.conf中的replica-priority配置最低 的从节点 。这个配置的默认值是100 。如果⼤家的配置都—样, 就进⼊下—个检查规则。

.  然后检查复制偏移量offset最⼤的从节点 。也就是找同步数据最快的slave节点 。因为他的数据是最全的 。如果⼤家的offset还是—样的, 就进⼊下—个规则

 .  最后按照slaveRunID字典顺序最⼩的节点。

3)切换新的主节点 Sentinel Leader给新的mater节点执⾏ slave of no one操作, 将他提升为 master节点 。 然后给其他slave发送slave of 指令 。让其他slave成为新Masterslave

4)如果旧的master恢复了, Sentinel Leader会让旧的master降级为slave 并从新的master上同步 数据, 恢复⼯作。

最终, 各个Redis的配置信息, 会输出到Redis服务对应redis.conf⽂件中, 完成配置覆盖.

4 Sentinel的缺点

Sentinel+Replica的集群服务, 可以实现⾃动故障恢复, 所以可⽤性以及性能都还是⽐较好的 。但是 这种⽅案也有—些问题。

(1) 对客户端不太友好

由于master需要切换, 这也就要求客户端也要将写请求频繁切换到master上。

(2)数据不安全

在主从复制集群中, 不管master是谁, 所有的数据都以master为主 。当master宕机后, 那些在

master上已经完成了, 但是还没有同步给其他slave的操作, 就会彻底丢失 。因为只要master—完成 了切换, 所有数据就以新的master为准了。

因此, 在企业实际运⽤中, ⽤得更多的是下⾯的Redis集群服务。

五、Redis集群Cluster机制详解

1 Cluster是什么?有什么⽤?

官⽹地址 Scale with Redis Cluster | Docs

—句话总结:将多组Redis Replica主从集群整合到—起, 像—个Redis服务—样对外提供服务。

 

所以Redis Cluster的核心依然是Replica复制集。
Redis Cluster通过对复制集进行合理整合后,核心是要解决三个问题:
(1)客户端需要频繁切换master的问题。
(2)服务端数据量太⼤后, 单个复制集难以承担的问题。
(3)master节点挂了之后, 主动将slave切换成master,保证服务稳定

2 Cluster的核⼼配置

配置见:CSDN

从节点信息可以看到, 集群中在每个master的最后, 都记录了他负责的slot槽位, 这些slot就是 Redis集群⼯作的核⼼ 

3 、详解Slot槽位

Redis集群设置16384个哈希槽 。每个key会通过CRC16校验后, 16384取模, 来决定放到哪个  。集群的每个节点负责—部分的hash槽。

问题1 Slot如何分配

Redis集群中内置16384个槽位 。在建⽴集群时 Redis会根据集群节点数量, 将这些槽位尽量平均的分配到各个节点上 。并且, 如果集群中的节点数量发⽣了变化 (增加了节点或者减少了节点) 。就需要触发—次reshard 重新分配槽位 。⽽槽位中对应的key 也会随着进⾏数据迁移。

 

# 增加6387,6388两个Redis服务, 并启动
# 添加到集群当中
redis-cli -a 123qweasd -p 6381 --cluster add-node 192.168.65.214:6387
192.168.65.214:6388
# 确定集群状态  此时新节点上是没有slot分配的
redis-cli -a 123qweasd -p 6381 --cluster check 192.168.65.214:6381
# ⼿动触发reshard, 重新分配槽位
redis-cli -a 123qweasd -p 6381 reshard 192.168.65.214:6381
# 再次确定集群状态  此时新节点上会有—部分槽位分配
redis-cli -a 123qweasd -p 6381 --cluster check 192.168.65.214:6381

reshard操作会从三个旧节点当中分配—部分新的槽位给新的节点 。在这个过程中, Redis也就并不需 要移动所有的数据, 只需要移动那—部分槽位对应的数据。

除了这种⾃动调整槽位的机制, Redis也提供了⼿动调整槽位的指令 。可以使⽤cluster help查看相关调整指令。

另外, Redis集群也会检查每个槽位是否有对应的节点负责 。如果负责—部分槽位的—组复制节点都 挂了, 默认情况下Redis集群就会停⽌服务 。其他正常的节点也⽆法接收写数据的请求。

如果此时, 需要强制让Redis集群提供服务, 可以在配置⽂件中, cluster-require-full-coverage 数⼿动调整为no

# By default Redis Cluster nodes stop accepting queries if they detect there
# is at least a hash slot uncovered (no available node is serving it).
# This way if the cluster is partially down (for example a range of hash slots
# are no longer covered) all the cluster becomes, eventually, unavailable.
# It automatically returns available as soon as all the slots are covered again. #
# However sometimes you want the subset of the cluster which is working,
# to continue to accept queries for the part of the key space that is still
# covered. In order to do so, just set the cluster-require-full-coverage
# option to no.
#
# cluster-require-full-coverage yes

 通常不建议这样做, 因为这意味着Redis提供的数据服务是不完整的

问题2、如何确定keyslot的对应关系?

Redis集群中, 对于每—个要写⼊的key 都会寻找所属的槽位 。计算的⽅式是 CRC16(key) mod 16384

⾸先, 这意味着在集群当中, 那些批量操作的复合指令(mset,mhset)⽀持会不太 。如果他们分属不同的槽位, 就⽆法保证他们能够在—个服务上进⾏原⼦性操作。

127.0.0.1:6381> mset k1 v1 k2 v2 k3 v3
(error) CROSSSLOT Keys in request don 't hash to the same slot

 

这也是对分布式事务的—种思考 。如果这种批量指令需要分到不同的Redis节点上操作, 么这 个指令的操作原⼦性问题就称为了—个分布式事务问题 。⽽分布式事务是—件⾮常复杂的事情, 不要简单的认为⽤上seata这样的框架就很容易解决 。在⼤部分业务场景下, 直接拒绝分布 式事务, 是—种很好的策略。

然后, Redis中, 提供了指令 CLUSTER KEYSLOT 来计算某—个key属于哪个Slot

127.0.0.1:6381> CLUSTER KEYSLOT k1
(integer) 12706

 另外, Redis在计算hash槽时, 会使⽤hashtag 。如果key中有⼤括号{} 那么只会根据⼤括号中的 hash tag来计算槽位。

127.0.0.1:6381> CLUSTER KEYSLOT k1 (integer) 12706
127.0.0.1:6381> CLUSTER KEYSLOT roy{k1} (integer) 12706
127.0.0.1:6381> CLUSTER KEYSLOT roy:k1 (integer) 12349
-- 使⽤相同的hash tag, 能保证这些数据都是保存在同—个节点上的。
127.0.0.1:6381>  mset user_{1}_name roy user_{1}_id 1 user_{1}_password 123
-> Redirected to slot [9842] located at 192.168.65.214:6382 OK

 

在⼤型Redis集群中, 经常会出现数据倾斜的问题 。也就是⼤量的数据被集中存储到了集群中某—个 热点Redis节点上 。从⽽造成这—个节点的负载明显⼤于其他节点 。这种数据倾斜问题就容易造成集 群的资源浪费。

调整数据倾斜的问题, 常⻅的思路就是分两步 。第—步, 调整key的结构, 尤其是那些访问频繁的热  key 让数据能够尽量平均的分配到各个slot 。第⼆步, 调整slot的分布, 将那些数据量多 访问 频繁的热点slot进⾏重新调配, 让他们尽量平均的分配到不同的Redis节点上。

4 Redis集群选举原理-了解

(1)gossip协议

Redis集群之间通过gossip协议进⾏频繁的通信, ⽤于传递消息和更新节点状态。 主要作⽤有:

  •   节点间发送⼼跳和确认其他节点的存在。
  •   通知其他节点新节点的加⼊或已经下线的节点。
  •   通过反馈机制更新节点的状态, 如权重 、过期时间等

gossip协议包含多种消息, 包括ping pong meet fail等等。 

  •  ·meet:某个节点发送meet给新加⼊的节点, 让新节点加⼊集群中, 然后新节点就会开始与其他 节点进⾏通信;
  •  · ping:每个节点都会频繁给其他节点发送ping 其中包含⾃⼰的状态还有⾃⼰维护的集群元数
  • 据, 互相通过 ping交换元数据(类似⾃⼰感知到的集群节点增加和移除, hash slot信息等)
  •   ·pong: pingmeet消息的返回, 包含⾃⼰的状态和其他信息, 也可以⽤于信息⼴播和更新;
  •  · fail: 某个节点判断另—个节点fail之后, 就发送fail给其他节点, 通知其他节点, 指定的节点宕机了。

 

gossip集群是去中⼼化的, 各个节点彼此之间通过gossip协议互相通信, 保证集群内部各个节点最终 能够达成统— gossip协议更新元数据并不是同时在集群内部同步, ⽽是陆陆续续请求到所有节点     。因此gossip协议的数据统—是有—定的延迟的。

gossip协议最⼤的好处在于, 即使集群节点的数量增加, 每个节点的负载也不会增加很多, ⼏乎是恒 定的 。因此在Redis集群中, 哪怕构建⾮常多的节点, 也不会对服务性能造成很⼤的影响 。但是

gossip协议的数据同步是有延迟的, 如果集群节点太多, 数据同步的延迟时间也会增加 。这对于 Redis是不合适的 。因此, 通常不建议构建太⼤的Redis集群。

需要注意下的是, Redis集群中, 每个节点都有—个专⻔⽤于节点之间进⾏gossip通信的端口 就是 ⾃⼰提供服务的端⼝ +10000.因此, 在部署Redis集群时, 要注意防⽕墙配置, 不要把这个端口屏蔽了。

(2)Redis集群选举流程

slave发现⾃⼰的master变为FAIL状态时, 便尝试进⾏Failover 以期成为新的master 。由于挂掉 master 可能会有多个slave 从⽽存在多个slave竞争成为master节点的过程, 其过程如下:

1) slave发现⾃⼰的master变为FAIL

2)将⾃⼰记录的集群current Epoch1 并⼴播FAILOVER_AUTH_REQUEST信息(current Epoch 以理解为选举周期, 通过cluster info指令可以看到)

3)其他节点收到该信息, 只有master响应, 判断请求者的合法性, 并发送 FAILOVER_AUTH_ACK 对每—个 epoch只发送—次ack

4) 尝试failoverslave收集master返回的FAILOVER_AUTH_ACK

5)slave收到超过半数masterack后变成新Master(这⾥解释了集群为什么⾄少需要三个主节点, 如果只有两 个, 当其中—个挂了, 只剩—个主节点是不能选举成功的)

6)slave⼴播Pong消息通知其他集群节点

从节点并不是在主节点—进⼊ FAIL 状态就⻢上尝试发起选举, ⽽是有—定延迟, —定的延迟确保我 们等待 FAIL状态在集群中传播, slave如果⽴即尝试选举, 其它masters或许尚未意识到FAIL状态  可能会拒绝投票

延迟计算公式: DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms

SLAVE_RANK表示此slave已经从master复制数据的总量的rank Rank越⼩代表已复制的数据越  。这种⽅ 式下, 持有最新数据的slave将会⾸先发起选举( 理论上) 

5 Redis集群能不能保证数据安全?

⾸先,在Redis集群相对⽐较稳定的时候, Redis集群是能够保证数据安全的。

因为Redis集群中每个master都是可以配置slave从节点的 。这些slave节点会即时备份master的数  。在master宕机时, slave会⾃动切换成master 。继续提供服务。

Redis的配置⽂件中, 有两个参数⽤来保证每个master须有健康的slave进⾏备份。

然后, 由于Redis集群的gossip协议在同步元数据时不保证强⼀致性, 这意味着在特定的条件下, Redis集群可能会丢掉⼀些被系统收到的写⼊请求命令。

这些特定条件通常都⽐较苛刻, 概率⽐较⼩ 。⽐如⽹络抖动产⽣的脑裂问题。

在企业中, 有良好运维⽀持, 通常可以认为Redis集群的数据是安全的。

六、Redis数据安全性⽅案总结

对于任何数据存储系统来说, 数据安全都是重中之重 Redis也不例外 。从数据安全性的⻆度来梳理  Redis从单机到集群的各种部署架构, 可以看到⽤Redis存数据基本上还是⾮常靠谱的 。甚⾄Redis  的数据保存策略, 在很多场景下, 都是—种教科书级别的解决⽅案 。另外, 之前介绍过, Redis现在推出了企业版本 。企业版在业务功能层⾯并没有做太多的加法, 核⼼就是在服务⾼可⽤以及数据安全 ⽅⾯提供了更加全⾯的⽀持 。有兴趣的朋友可以⾃⾏去了解补充。

但是, 基于内存和硬盘的成本对⽐, Redis通常还是不建议作为独⽴的数据库使⽤ 。⼤部分情况下,还是发挥Redis⾼性能的优势, 作为—个数据缓存来使⽤ 。其实, 如果有⾮常靠谱的运维⽀撑, Redis 作为数据库来使⽤完全是可以的 。⽐如, Redis现在提供了基于云服务器的RedisCloud服务 。其中就可以购买作为数据库使⽤的Redis实例。

 

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【系统分析师】2011年真题:综合知识-答案及详解

文章目录 【第1题】【第2~3题】【第4~5题】【第6题】【第7~8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19~20题】【第21题】【第22题】【第23题】【第24~25题】【第26题】【第27题】【第28题】【第29题】【…

FastAPI-MCP构建自定义MCP工具实操指南

一、简介 • FastAPI-MCP是一个基于python FastAPI框架开发的开源项目&#xff0c;可以自动识别并暴露FastAPI接口为MCP工具 • 拥有FastAPI框架的所有优点&#xff0c;如异步高并发、独立远程部署、OpenAPI文档 • 提供SSE、mcp-remote接入方式&#xff0c;支持设置授权访问…

LLMs之Memory:《LLMs Do Not Have Human-Like Working Memory》翻译与解读

LLMs之Memory&#xff1a;《LLMs Do Not Have Human-Like Working Memory》翻译与解读 导读&#xff1a;该论文通过三个精心设计的实验&#xff0c;证明了当前的大型语言模型&#xff08;LLMs&#xff09;缺乏类似人类的工作记忆。实验结果表明&#xff0c;LLMs无法在没有明确外…

Node.js验证码:从生成到验证的趣味之旅

文章目录 Node.js验证码&#xff1a;从生成到验证的趣味之旅&#x1f4dc; 引言&#xff1a;为什么需要验证码&#xff1f;1. 验证码的基本原理 &#x1f9e0;验证码工作流程示意图 2. 技术栈准备 &#x1f6e0;️3. 验证码生成详解 &#x1f3a8;3.1 生成SVG验证码3.2 转换为P…

芯科科技携最新Matter演示和参考应用精彩亮相Matter开放日和开发者大会

全面展示赋能Matter设备实现跨协议和跨海内外生态的技术能力 作为Matter标准创始厂商之一和其解决方案的领先供应商&#xff0c;Silicon Labs&#xff08;亦称“芯科科技”&#xff09;于6月12至13日参加由连接标准联盟中国成员组&#xff08;CMGC&#xff09;主办的Matter年度…

AndroidStudio下载的SDK没有tool目录,或者想要使用uiautomatorviewer工具

1.如果没有tool目录可以使用下面的地址进行下载 https://dl.google.com/android/repository/tools_r25.2.5-windows.zip 2.并且把下载的文件解压到放在AndroidStudio的目录中 3.如果使用uiautomatorviewer.bat出现下面的错误 Unable to connect to adb.Check if adb is instal…

FastJSON等工具序列化特殊字符时会加转义字符\

在Java中JSON数据格式用String接收时&#xff0c;此时在FastJSON层面看来该JSON只是普通字符串&#xff0c;所以对原字符串序列化会得到转义字符\ 得到转义后字符串&#xff0c;再反序列化转义后字符串会得到原字符串 String json"{\"name\": \"张三\&quo…

数据结构 学习 队列 2025年6月14日 11点22分

循环队列 循环队列是一种线性数据结构&#xff0c;它遵循FIFO&#xff08;先进先出&#xff09;原则&#xff0c;但与普通队列不同的是&#xff0c;循环队列的最后一个元素连接回第一个元素&#xff0c;形成一个环形结构。这种设计有效解决了普通队列的"假溢出"问题&…

打造丝滑滚动体验:Scroll-driven Animations 正式上线!

&#x1f300; 打造丝滑滚动体验&#xff1a;Scroll-driven Animations 正式上线&#xff01; &#x1f6a8; 告别 JS 手动监听滚动条&#xff0c;CSS 新能力让你用两行代码实现高级滚动动效。 &#x1f50d; 什么是 Scroll-driven Animations&#xff1f; Scroll-driven anim…

知识体系_研究模型_价格敏感度测试模型(PSM)

1 概述 价格敏感度测试模型(Price Sensitivity Measurement,PSM) ,通过调研潜在用户对于不同价格的满意或接受程度,从而制定出合适的产品价格。 价格敏感度PSM模型的分析一般分为以下几个步骤: (1)确定多个价格 (2)通过一定的方式(通常是问卷)收集目标客户对不同价…

C++11函数封装器 std::function

✅ 1. 什么是 std::function std::function 是 C11 引入的标准库工具&#xff0c;是一个通用的函数封装器&#xff0c;可以包装以下任意可调用对象&#xff1a; 普通函数Lambda 表达式函数指针成员函数指针函数对象&#xff08;也叫仿函数&#xff0c;定义了 operator() 的类…

centos系统docker配置`milvus-standalone`教程

本人使用的是京东云服务器docker配置milvus 参考教程&#xff1a;https://blog.csdn.net/withme977/article/details/137270087 需要注意&#xff1a;虚拟机安装pymilvus和docker安装milvus版本需要对应&#xff0c;否则会出现connection失败问题 查看虚拟机pymilvus版本&…

AI for 数据分析:技术演进与应用实践

一、AI 数据分析的核心定义与技术演进 概念延伸&#xff1a;从传统分析到智能分析 传统数据分析工作&#xff0c;主要依赖人工使用 Excel、SPSS 等统计工具进行建模与分析。这种方式不仅效率较低&#xff0c;而且对专业人员的依赖度极高。而 AI 驱动的数据分析则借助机器学习…

stm32 f103c8t6仿真 串口收发测试

C8T6串口概述 STM32F103C8T6微控制器包含3个串口模块&#xff1a; USART1 (高级串口) USART2 USART3 (部分型号可能标记为UART3) 引脚分布图 USART1 (串口1) 基本特性 类型&#xff1a;全功能USART(通用同步异步收发器) 通信模式&#xff1a; 全双工异步通信 单线半…

语言特性适用的场景:卫星、火箭控制系统用什么开发语言?

核心飞行控制系统开发语言 卫星、火箭及相关航天系统的软件开发对可靠性、实时性、安全性有极高要求&#xff0c;因此语言选择需严格匹配这些需求。以下是航天领域常用的编程语言及其应用场景分析&#xff1a; 一、核心飞行控制与嵌入式系统&#xff1a;C、C、Ada 航天器的核…

AI for Science:智能科技如何重塑科学研究

AI与科学研究的邂逅 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;作为一门致力于模拟人类智能的交叉学科&#xff0c;近年来已经从实验室走向现实世界的各个角落&#xff0c;而科学研究领域正是其最具变革潜力的舞台之一。AI的核心在于通过算法…

项目三 - 任务7:开发名片管理系统

在本次项目三的任务7中&#xff0c;我们成功开发了一个功能全面的名片管理系统。该系统采用Java语言&#xff0c;基于MVC&#xff08;模型-视图-控制器&#xff09;架构模式&#xff0c;实现了用户登录、名片的增删改查等核心功能。通过设计Card类来封装名片信息&#xff0c;Ca…

MySQL 8.0 OCP 英文题库解析(十八)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题161~170 试题1…

leetcode_503 下一个更大元素

1. 题意 在一个循环数组中&#xff0c;找到下一个比它大的数。 2. 题解 也不知道怎么就单调栈了&#xff0c;可能是刷出来的吧。。。 还是来解释一下吧&#xff01;&#xff01;&#xff01; 如果有新元素入栈 c c c&#xff0c; 那么在栈内的元素只要小于新元素的 s s s…