集群是个好东西,一个应用解决不了的,多个应用共同分担。提高了程序的高可用!

介绍redis-benchmark

项目遇到性能问题,基本都会以集群方式去解决。在讲Redis的集群之前,我们先学会Redis的性能压力测试。--redis-benchmark

redis 服务在windows环境下的启动命令是redis-server.exe ,在此文件夹,往往还存在一个新的文件redis-benchmark.exe,此文件就是用来进行redis的压力测试的!(linux环境也是一样的!) 中文官网说明:http://www.redis.cn/topics/benchmarks.html

Mac 安装Redis

# Mac 显示隐藏文件夹
defaults write com.apple.finder AppleShowAllFiles -boolean true ; killall Finder
# 1 查看是否安装 Homebrew
brew --version

# 2 安装redis
brew install redis

# 3 卸载redis
brew cleanup redis

# 4 启动redis
/opt/homebrew/opt/redis/bin/redis-server /opt/homebrew/etc/redis.conf

测试性能

redis-benchmark -q -n 100000

仅仅截取常规的命令速度,可以看出来M1 Pro,每秒处理10万个请求没问题!我也加大了10万连接数调整为20万,实际速度能达到12万左右

实际每秒10万的处理性能已经很不错了!足够面对企业服务器的需求了!

Redis主从复制

参照:https://www.jb51.net/article/224568.htm

上述图片描述的是:1个主库 + 2 个从库。同时两个从库,本身就各带有2个从库。

Redis集群数据复制的原理

1、同步SYNC:主服务器收到SYNC命令后,生成RDB快照文件,然后发送给从服务器

  1. 发送psync命令进行数据同步,由于是第一次进行复制,从节点没有复制偏移量和主节点的运行ID,所以发送psync-1。
  2. 主节点根据psync-1解析出当前为全量复制,回复+FULLRESYNC响应。
  3. 从节点接收主节点的响应数据保存运行ID和偏移量offset
  4. 主节点执行bgsave保存RDB文件到本地
  5. 主节点发送RDB文件给从节点,从节点把接收的RDB文件保存在本地并直接作为从节点的数据文件
  6. 对于从节点开始接收RDB快照到接收完成期间,主节点仍然响应读写命令,因此主节点会把这期间写命令数据保存在复制客户端缓冲区内,当从节点加载完RDB文件后,主节点再把缓冲区内的数据发送给从节点,保证主从之间数据一致性。
  7. 从节点接收完主节点传送来的全部数据后会清空自身旧数据
  8. 从节点清空数据后开始加载RDB文件
  9. 从节点成功加载完RDB后,如果当前节点开启了AOF持久化功能, 它会立刻做bgrewriteaof操作,为了保证全量复制后AOF持久化文件立刻可用。

2、命令传播:主服务器收到客户端修改数据命令后,数据库数据发生变化,同时将命令缓存起来,然后将缓存命令发送到从服务器,从服务器通过载入缓存命令来达到主从数据一致。

命令传播的方式是:使用psync {runId} {offset}

下面介绍的是命令传播中图遇到失败的情况。

  1. 当主从节点之间网络出现中断时,如果超过repl-timeout时间,主节点会认为从节点故障并中断复制连接
  2. 主从连接中断期间主节点依然响应命令,但因复制连接中断命令无法发送给从节点,不过主节点内部存在的复制积压缓冲区,依然可以保存最近一段时间的写命令数据,默认最大缓存1MB。
  3. 当主从节点网络恢复后,从节点会再次连上主节点
  4. 当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行ID。因此会把它们当作psync参数发送给主节点,要求进行部分复制操作。
  5. 主节点接到psync命令后首先核对参数runId是否与自身一致,如果一 致,说明之前复制的是当前主节点;之后根据参数offset在自身复制积压缓冲区查找,如果偏移量之后的数据存在缓冲区中,则对从节点发送+CONTINUE响应,表示可以进行部分复制。
  6. 主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。

了解上述两种机制后,Redis集群数据复制的原理就是:从库向主库发送SYNC命令,主库开始执行bgsave生成RDB文件,发送给从库。如果此时主库生成完RDB文件,主库依旧有命令操作数据变化,主库就利用命令传播机制,将主库的变化命令给从库。

看一下别人上传的时序图

配置Redis一主二从结构

不同版本的Redis配置命令发生变化了:replicaof是新版本的命令,旧版本是slaveof命令

# 主节点 master
port 6379
# 从节点1 slave1
port 6380
# replicaof <masterip> <masterport>
replicaof 127.0.0.1 6379
# 从节点2 slave2
port 6381
# replicaof <masterip> <masterport>
replicaof 127.0.0.1 6379

启动主从Redis

以下均是 Redis启动命令
 /opt/homebrew/opt/redis/bin/redis-server /opt/homebrew/etc/redis01.conf

 /opt/homebrew/opt/redis/bin/redis-server /opt/homebrew/etc/redis02.conf

 /opt/homebrew/opt/redis/bin/redis-server /opt/homebrew/etc/redis03.conf

检查Redis 主从状态信息

进入Redis-Cli
redis-cli -p 6379

输入info,执行后会打印大量的信息,如果想了解具体含义,可以前往:https://www.zanglikun.com/7123.html
info

Redis 主从复制 优缺点

优点:提供了可用性(可以实现读写分离),从库多了,宕机一个问题不大。

缺点:

  • master节点挂了需要人工干预切换master节点
  • master节点宕机后,恢复瞬间会有大量从节点SYNC命令进来,Master节点 IO压力大。

Redis哨兵模式 Redis Sentinel

什么是Redis哨兵模式?

Redis主从复制有个最大的缺点就是,主节点挂了,需要人工干预才能保证业务的正常运行。

Redis哨兵对主从服务器做一个监视的任务。一旦发现主服务器宕机了,就迅速启动相应的规则将某一台从服务器升级为主服务器,无需人工干预,更稳定更快。

哨兵本质就是一个Redis服务器,只是用于监控,不可set,get相关命令!

使用Redis哨兵模式的前提是,至少拥有Redis集群的一个主从结构!

Redis哨兵配置文件

配置文件必须加入下方内容

sentinel monitor master-name ip port quorum

# 配置master节点的密码
#sentinel auth-pass master-name 我是密码

上述配置参数讲解

  • master-name 监控主节点的名字,多个哨兵需要配置一致 一般配置为 mymaster
  • ip 表示:redis主节点ip
  • port 表示:redis主节点port
  • quorum 表示:判定某节点被哨兵标记为挂掉的哨兵数量,一般配置为哨兵数量除2再减一

3个哨兵的配置

port 26379
dir /tmp/redis-test-data-dir
sentinel monitor mymaster 127.0.0.1 6379 2 
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
port 26380
dir /tmp/redis-test-data-dir
sentinel monitor mymaster 127.0.0.1 6379 2 
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
port 26381
dir /tmp/redis-test-data-dir
sentinel monitor mymaster 127.0.0.1 6379 2 
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

启动哨兵 (需提前开启redis主从模式)

哨兵会自动组建集群:我们一般不会单独配置一个哨兵,而是配置哨兵数量为:大于1的奇数,一般为三个。因为哨兵需要进行投票。如果只有1个哨兵,发现redis服务器有问题,很有可能是其自己的网络问题。如果有2个哨兵,一个哨兵,发现故障,另一个哨兵没发现故障,我们就不知要不要切换新的master节点了。如果有3个哨兵,我们就可以设定半数投票机制。如果认定失败数大于总哨兵数一半以上,就认定是相对比较合理的。如果哨兵设置为偶数个,相互投票,可能投票数打平。建议为大于1的奇数

下面是启动3个哨兵的命令
/opt/homebrew/opt/redis/bin/redis-sentinel /opt/homebrew/etc/redis-sentinel01.conf

/opt/homebrew/opt/redis/bin/redis-sentinel /opt/homebrew/etc/redis-sentinel02.conf

/opt/homebrew/opt/redis/bin/redis-sentinel /opt/homebrew/etc/redis-sentinel03.conf

当每新开启一个哨兵后,前面的哨兵的配置文件就会发生变化,添加了新哨兵的信息!

如果发生主节点宕机,我们可以简单干预主从切换,那就需要在redis-server端(非哨兵)的配置文件,加入replica-priority参数,此数值越小,被推为主节点优先级越高!选值是 0-100,如果是0,则不会被选举为主节点。设置为1即可。

哨兵原理

1、检测主节点挂了

2、确定主节点挂了,Sentinel将server2升级为主服务器,server3/4从新的主服务器进行复制。同时等待server1的再次上线。

3、如果Server1此事正常了。Sentinel系统也可以主动降级主节点为从节点,将从节点升级为主节点。

底层实现机制

1、监控阶段

哨兵1连接master,获取子节点与其记录的哨兵信息,再与master建立cmd连接,如果有其他哨兵,使用发布订阅,公开获取最新的redis服务器信息,其他哨兵获取后,同步自己的数据

哨兵1通过上一步的信息,连接其他Redis子节点并获取其记录的哨兵信息,并与其他哨兵建立cmd连接

哨兵2连接master,获取子节点与其他哨兵信息,并与master建立cmd连接

哨兵2通过上一步的信息,连接子节点与其他哨兵信息,并建立与子节点cmd连接,于此同时,使用发布订阅,公开获取最新的redis服务器信息,其他哨兵获取后,同步自己的数据

2、通知阶段

每个哨兵都会与redis服务器进行通信,通信失败后,就会给此服务器标记状态,分为:

sdown主观下线 odown客观下线

sdown 是有哨兵与任一redis节点进行通信,如ping pong,如果在down-after-milliseconds时间内此节点没有响应,则该哨兵认为此redis节点主观下线了。

如果是认定master主观下线的哨兵则会通过指令sentinel is-masterdown-by-addr寻求其它哨兵对主节点的判断,当超过quorum(在sentinel配置中配置的法定人数)个数,此时哨兵节点则认为该主节点确实有问题,这样就客观下线了。一旦触发客观下线,就会触发第三步:故障转移

尚不清晰,非master节点宕机,哨兵会不会判定客观下线,我本机测试只有sdown

3、故障转移

哨兵之间推选出故障转移的哨兵

故障转移的哨兵,拿到所有节点,经过一些列判断,选出主redis服务器

通知选举出的主redis服务器,你作为master服务器了

通知其他从服务器:新的master信息

redis脑裂

redis脑裂是当前master节点与所有哨兵断开连接,但实际是正常的,但是原有哨兵,就安排了新的master出来。也就是说,同时存在了2个master了。客户端有多个连接,有的连接老master,有的连接新master。2个master之间数据是不一样的,过了一段时间,老master网络正常了,加入集群中,就会作为从节点,同步新master的数据,(同步过程是,A发起同步请求,B会打包rdb文件,A拿到rdb文件 A执行flusb db,A还原rdb数据)导致老master在没加入集群期间,新数据的丢失!

解决redis脑裂

redis配置文件添加

min-slaves-to-write :是指主库最少得有 N 个健康的从库存活才能执行写命令。建议设定为:slaves的数量/2 +1

min-slaves-max-lag :是指从库和主库进行数据复制时的 ACK 消息延迟的最大时间;

新版本Redis 配置变更为:

min-replicas-to-write 3
min-replicas-max-lag 10

如果同时存在多个master,必然有1个master不会拥有子节点。设置min-slaves-to-write后,老master发现没有足够的从节点,就会拒绝写入服务。如果同时设定了min-slaves-max-lag,就变为足够满足从节点数且其复制时间不超过指定时间,master才能正常使用。如果无法满足master就会拒绝写入!大大减少了脑裂造成的数据丢失!脑裂一般无法满足一个数据不丢失!

Redis哨兵模式的缺点

优点:主要用来监控redis主从集群,提高了redis 主从集群的可用性。

缺点:Redis较难支持在线扩容(我不是很理解在线扩容的含义)

Cluster模式

Redis Cluster是一种服务器 Sharding 技术,redis 3.0版本开始正式提供。
哨兵模式基本已经实现了高可用,但是每台机器都存储相同内容,很浪费内存,所以Redis Cluster实现了分布式存储。每台机器节点上存储不同的内容。

Cluster模式的每一个主机都是主节点,同时会对每个节点进行Slot范围划分。大意就是。每次操作执行读写操作时,会依据key做算法判定,得出slot数,针对slot范围,读写操作就针对某个节点了。

操作落在那个节点公式是:slot = crc16("KeyName") % 16384

Redis Cluster数据分片原理

redis 数据分片使用的是hash slot, redis集群有16384个哈希槽(用bitmap存储就是占有内存2kb,大意就是最多16384个节点,正常业务不会超过那么多的节点的),每个Key通过CRC16校验后对16384取模来决定放置哪一个槽。
当存取redis key时候,redis会根据CRC16算法得到一个结果,然后把结果和16384求余,通过这个值去对应得节点获取数据。
这个时候,应用客户端实际上只需要连接其中任意一个节点即可,然后Redis Cluster 中每个节点都保存了其他节点得槽信息。这样当存取key计算完槽之后,通过保存槽信息从配置中获取节点信息,然后再去对应得节点获取数据。

Redis建议Cluster模式是3主3从模式,一共6个节点。

如果构建了3主3从模式。

如果:主节点挂了,会把从节点推选为新主节点。如果老主节点恢复,就加入从节点。

如果:主节点挂了,从节点也挂了,整个集群拒绝执行。

1、实现了分布式存储,节省了内存

特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取全部资料 ❤