【Redis入门】Redis集群,主从复制,哨兵模式
👉写在前边
- 上篇我们了解了 【Redis入门】Redis事务中的乐与悲,这篇我们将进入redis中的集群篇--涵盖了主从复制,哨兵模式,集群搭载三部分。本篇也算是2022年第一篇,把2021年redis留下来的坑填上去,点击这里,打开我的2021~
主从复制
主(写)从(读)
**从机只能读,不能写
一主二仆(附步骤)
拷贝多个redis.conf文件include(写绝对路径) ??
对应不同服务器不同配置文件
新建redis_7001.conf 修改conf
注意要开启安全组端口
#引入我们原来的redis.conf文件(根据目录引入)
include ../redis.conf
#在引入的基础上,修改必要的选项
pidfile /var/run/redis_7001.pid
port 7001
dbfilename dump7001.rdb
appendonly no
daemonize yes
同理创建另外两个conf,修改相应的pid文件,port,dufilename名字
#引入我们原来的redis.conf文件(根据目录引入)
include ../redis.conf
#在引入的基础上,修改必要的选项
pidfile /var/run/redis_7002.pid
port 7002
dbfilename dump7002.rdb
appendonly no
daemonize yes
#引入我们原来的redis.conf文件(根据目录引入)
include ../redis.conf
#在引入的基础上,修改必要的选项
pidfile /var/run/redis_7003.pid
port 7003
dbfilename dump7003.rdb
appendonly no
daemonize yes
查看三台主机运行情况
info replication
slaveof ip地址 端口
成为某个实例的从服务器
从机挂掉后,重启没办法恢复成xx的从机
从机重启需重设:slaveof 127.0.0.1 6379
但挂掉期间主服务的操作,重启后还是可以看到的
薪火相传
- 上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力,去中心化降低风险
中途变更转向:会清除之前的数据,重新建立拷贝最新的 风险是一旦某个slave宕机,后面的slave都没法备份 主机挂了,从机还是从机,无法写数据了
反客为主
小弟上位
主服务器挂掉后,从服务器只需要用 slaveof no one 就可以上位,变成主服务器了!
但是这里毕竟得自己手动输入命令,才能上位,还是不太方便的在实际的业务场景中,那么如何实现更好的方法呢,得来看看后边要讲到的哨兵模式
复制原理
- 当从服务器连接上主服务器后,从服务器会主动向主服务器请求数据同步的消息
从服务器主动
- 主服务器接受到后,就会进行持久化操作,然后把rdb文件发送给从服务器,从服务器读取rdb文件以达到同步的效果
- 每次主服务器进行了写操作后,也会跟从服务器进行数据同步
主服务器主动
全量复制:slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
但是只要是重新连接master,全量复制将被自动执行
哨兵模式
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库
- 哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例 。
自定义的/myredis目录下新建sentinel.conf文件,名字绝不能错
配置哨兵,填写内容
sentinel monitor mymaster 127.0.0.1 6379 1
其中mymaster为监控对象起的服务器名称,1 为至少有多少个哨兵同意迁移的数量。 设置为1的话,只需要一个哨兵同意就可以切换,设置成2则需要有两个哨兵都同意才进行切换(将从库转换为主库)
启动哨兵
执行redis-sentinel /myredis/sentinel.conf
当主机挂掉,从机选举中产生新的主机
(大概10秒左右可以看到哨兵窗口日志,切换了新的主机) 哪个从机会被选举为主机呢?根据优先级别:slave-priority 原主机重启后会变为从机。
新皇登基了已经
复制延时
由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。
故障恢复
优先级在redis.conf中默认:slave-priority 100,值越小优先级越高
目前最新版本已经改名为 : replica-priority 默认是100
- 偏移量是指获得原主机数据最全的
每个redis实例启动后都会随机生成一个40位的runid
集群(无中心化)
***好处
主从模式,薪火相传模式,主机宕机,导致ip地址发生变化,应用程序中配置需要修改对应的主机地址、端口等信息。
之前通过代理主机来解决,但是redis3.0中提供了解决方案。就是无中心化集群配置。
代理
每一个又都需要从机,总共就需要8台
无中心化
只需要6台,每一台都能作为入口,然后再去转移(互相访问连通)
Redis 集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N。
- Redis 集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。
搭载集群
配置文件
同理拷贝出其他5个,总共是7001-7006(要开放相应端口,修改文件中的对应各种数字)
include ../redis.conf
pidfile /var/run/redis_7001.pid
port 7001
dbfilename dump7001.rdb
cluster-enabled yes
cluster-config-file nodes-7001.conf
cluster-node-timeout 15000
快速替换的小技巧
:%s/7001/7002g
帝皇侠合体
- redis-cli --cluster create --cluster-replicas 1 10.0.8.13:7001 10.0.8.13:7002 10.0.8.13:7003 10.0.8.13:7004 10.0.8.13:7005 10.0.8.13:7006
redis-cli --cluster create --cluster-replicas 1 后边是 host:port host:port
- 注意如果是阿里云或者腾讯云的,这里得用内网ip!!!!
有设置密码的还得在最后补充 -a 密码
--replicas 1 采用最简单的方式配置集群,一台主机,一台从机,正好三组。
输入yes
成功界面
普通方式登录
- 可能直接进入读主机,存储数据时,会出现MOVED重定向操作。所以,应该以集群方式登录。
-c 采用集群策略连接
- ./redis-cli -c -p 7001
选择任意一个端口连接都可以,设置数据会自动切换到相应的写主机
查看节点信息
- CLUSTER NODES
分配原则
一个集群至少要有三个主节点。 选项--cluster-replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。 分配原则尽量保证每个主数据库运行在不同的IP地址,每个从库和主库不在一个IP地址上。
slot
一个 Redis 集群包含16384 个插槽(hash slot),数据库中的每个键都属于这16384 个插槽的其中一个, 集群使用公式 CRC16(key) % 16384
- 来计算键key 属于哪个槽,其中CRC16(key) 语句用于计算键key 的CRC16 校验和。
集群中的每个节点负责处理一部分插槽。举个例子,如果一个集群可以有主节点,其中:
- 节点 A 负责处理0号至5460号插槽。
- 节点 B 负责处理5461号至10922号插槽。
- 节点 C 负责处理10923号至16383号插槽。
这里的分配有点类似哈希函数,主要是为了能够尽量平均分配,让三个主节点能够平均分担压力
- 不过这里如果计算出来的值一样(并不会像哈希一样出现冲突),而是让一个插槽放多个数据就好了
不在一个slot下的键值,是不能使用mget,mset等多键操作。
- 可以通过{}来定义组的概念,从而使key中{}内相同内容的键值对放到一个slot中去。
此时是根据{}内user计算,{}里的内容一样,自然会放到同一个slot中去
计算重定向(无中心化的实现方式)
- 通过计算,然后去重定向到相应的节点上,这样就可以实现各个节点能够互相连通,自然而然每个节点都能作为入口了,因为他们可以重定向到别的节点,互相连通互相访问!
主机挂掉了???
- 此时7003 fail掉了,此处还有待进一步验证,现在服务器上挂着几个项目不敢乱搭,寒假再拿另外一个服务器来试试。
JRedis集群开发
即使连接的不是主机,集群会自动切换主机存储。主机写,从机读。 无中心化主从集群。无论从哪台主机写的数据,其他主机上都能读到数据。
public class JedisClusterTest {
public static void main(String[] args) {
Set<HostAndPort>set =new HashSet<HostAndPort>();
set.add(new HostAndPort("192.168.31.211",6379));
JedisCluster jedisCluster=new JedisCluster(set);
jedisCluster.set("k1", "v1");
System.out.println(jedisCluster.get("k1"));
}
}
另一种版本
public static void main(String[] args) {
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
//Jedis Cluster will attempt to discover cluster nodes automatically
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 6371));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 6372));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 6373));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 6374));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 6375));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 6376));
JedisCluster jc = new JedisCluster(jedisClusterNodes);
jc.set("foo", "bar");
String value = jc.get("foo");
System.out.println(" ===> " + value);
}
💠下篇预告
- 到这里,redis的基本知识篇差不多就结束了,剩下的可能还有面试篇的三种缓存问题,如何解决,应用篇redis在项目中的实际应用场景,以及高级篇redis原理,有机会我们再来聊一聊。
参考
- 尚硅谷Redis6视频
- 狂神说Redis视频
转载自:https://juejin.cn/post/7048185004626542622