Redis集群和Sentinel一些基础问题

51 阅读3分钟

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