Redis集群
主从复制
假如现在我有3个Redis,我要把他们组成集群,一个叫主节点master,另外两个从节点叫slave0和slave1
现在有一个问题。我们为什么要用redis集群?
- 显而易见的,是为了增加吞吐量
- 做redis数据的热备份,当节点出现故障的时候,可以快速恢复
Redis集群master和slave分别负责什么工作?
- master节点主要负责读写操作
- slave主要负责读操作
slave节点可不可以写?
- slave节点其实是可以通过配置,开启写功能的,不过也会有相应的问题
- Redis集群采用的是主从复制的同步方式,假如你在slave节点写的话,其他节点是拿不到数据的。
主从同步是如何发起的?
- 由slave主动拉取
主从同步是如何进行的?
- 从节点发送
PSYNC命令- Replication ID :主节点的唯一标识。
- Offset 从 :节点当前复制偏移量(用于判断增量复制条件)
- 根据偏移量决定是全量同步还是增量同步
- 主节点执行
BGSAVE命令,对生成RDB快照 - 生成期间,主节点继续处理写命令,并将这些命令缓存到复制缓冲区(Replication Buffer)
- RDB生成完成后,主节点将其发送给从节点
- 从节点接收完成后,清空旧数据,加载RDB文件到内存。
- 主节点将生成RDB期间缓存的写命令发送给从节点,确保数据完全一致。
主从模式有个非常不集群的地方,如果master节点丢失了,slave是不会自动选举为master的!需要你手执行命令SLAVEOF NO ONE,选择slave为master
那有没有办法让我们的Redis集群自动选举呢???
- Sentinel
Sentinel
Redis的Sentinel模式,可以帮我们监控Redis集群以及在Master掉线以后,自动提升要给Slave作为Master
- 直接在Master主从集群上,加一个Sentinel帮助集群自动选举Master可以么?
- 可以,但是如果你是Master负责写,Slave负责读,你的Redis配置写死了Master的地址。直接加一个Sentinel就会有问题。如果你的Master挂了,Slave0变成了Master,原先的Master重新启动后会变成Slave。Slave默认是没有写能力的(也不建议去写),如果你的Reids客户端通过Master的Ip地址配置的,那么你的Master服务降级后,就丢失了写的能力
- 当你使用了sentinel以后,你要通过连接sentinel,去对Redis进行读写
- 如果要配置master写入,slave读取,可以怎么做?
@Configuration
public class RedisConfiguration {
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
// 配置Sentinel
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
.master("redis-master") // 与配置中的master名称一致
.sentinel("host.docker.internal", 26379);
// 设置读写策略:优先从从节点读取
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(ReadFrom.REPLICA_PREFERRED)
.build();
return new LettuceConnectionFactory(sentinelConfig, clientConfig);
}
}
最后给上一份docker-compose的yarm
仅供参考用,具体配置需要自己调整
services:
redis-master:
image: redis:6.2.5
container_name: redis-master
command: ["redis-server", "--requirepass", "123123", "--masterauth", "123123"]
ports:
- "6379:6379"
volumes:
- ./redis-config/redis.conf:/usr/local/etc/redis/redis.conf
networks:
- redis-net
redis-slave1:
image: redis:6.2.5
container_name: redis-slave1
command: ["redis-server", "--slaveof", "redis-master", "6379", "--requirepass", "123123", "--masterauth", "123123"]
ports:
- "6380:6379"
depends_on:
- redis-master
volumes:
- ./redis-config/redis.conf:/usr/local/etc/redis/redis.conf
networks:
- redis-net
redis-slave2:
image: redis:6.2.5
container_name: redis-slave2
command: ["redis-server", "--slaveof", "redis-master", "6379", "--requirepass", "123123", "--masterauth", "123123"]
ports:
- "6381:6379"
depends_on:
- redis-master
volumes:
- ./redis-config/redis.conf:/usr/local/etc/redis/redis.conf
networks:
- redis-net
sentinel:
image: redis:6.2.5
container_name: redis-sentinel
command: ["redis-sentinel", "/etc/redis-config/sentinel.conf"]
volumes:
- "./config:/etc/redis-config"
depends_on:
- redis-master
- redis-slave1
- redis-slave2
ports:
- "26379:26379"
networks:
- redis-net
volumes:
redisinsight_data:
networks:
redis-net:
driver: bridge
# sentinel.conf
sentinel monitor redis-master 你的ip 6379 1
# 你的master节点密码
sentinel auth-pass redis-master 123123
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 60000
sentinel resolve-hostnames yes
# redis.conf
bind 0.0.0.0
protected-mode no