Redis--基础知识点--22--实战:docker 搭建 redis 的单机模式/主从模式/哨兵模式/集群模式

1 单机模式

1.1 简介

redis作为一种高效的缓存框架,使用是非常广泛的,在数据存储上,在运行时其将数据存储在内存中,以实现数据的高效读写,并且根据定制的持久化规则不同,其会不定期的将数据持久化到硬盘中。另外相较于其他的NoSql数据库,redis提供了非常丰富的数据结构。在这些存储结构的基础上,redis为用户提供了非常丰富的操作选择。

1.2 实战:采用docker-compose
1.2.1 docker和docker-compose都已安装好,并docker已启动且下载好redis镜像。
1.2.2 修改redis.conf

下载地址
配置文件采用默认即可。将redis.conf放到指定的目录,比如:/home/dc2-user/docker_data/myredis/redis.conf

尤其注意

daemonize no  

保持原来的no,不要修改为yes,否则在docker中启动redis后会立即停止。因为docker机制所致,启动的容器中必须有一个前台进程,否则容器会立即停止,避免占用资源。

不使用密码,直接外网连接,redis.conf修改如下

bind 0.0.0.0
protected-mode no

补充

  • protected-mode yes时,不设置密码只能进行本地连接,设置密码以后可以外网连接。
  • protected-mode no时,不设置密码也可以外网连接。

使用密码进行外网连接,redis.conf修改如下

bind 0.0.0.0
protected-mode yes
requirepass 123456
1.2.3 编写docker-compose.yml文件

该文件的路径放在/home/dc2-user/docker_data/myredis/下,会默认docker-compose.yml所在目录的目录名为项目名。

version: '3'
services:
    myredis:
        image: redis
        ports:
            - 6379:6379
        volumes:
            - ./conf/redis.conf:/etc/redis/redis.conf   
            - ./data:/data:rw
            - ./logs:/usr/local/redis/logs
        container_name: myredis
        networks: 
            - mynet
        command: redis-server /etc/redis/redis.conf
networks:
    mynet:
        driver: bridge
1.2.4 启动容器

进入/home/dc2-user/docker_data/myredis/目录下,执行以下命令

docker-compose up -d

查看容器是否启动成功

docker-compose ps
1.2.5 测试连接redis
通过nc本地访问docker中的redis

没有设置密码

[root@zhangsan myredis]# echo -en 'ping\n' | nc 127.0.0.1 6379
+PONG  # 表示通过nc访问docker中的redis成功

设置了密码

[root@zhangsan myredis]# echo -en 'auth 123456\nping\n' | nc 127.0.0.1 6379
+PONG  # 表示通过nc访问docker中的redis成功
进入容器使用redis-cli访问redis

没有设置密码

[root@zhangsan myredis]# docker-compose exec myredis bash
root@a0d9b9632791:/data# echo -en 'ping\n' | redis-cli
+PONG

设置了密码

[root@zhangsan myredis]# docker-compose exec myredis bash
root@a0d9b9632791:/data# echo -en 'ping\n' | redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
PONG

2 主从模式

2.1 简介

redis单例提供了一种数据缓存方式和丰富的数据操作api,但是将数据完全存储在单个redis中主要存在两个问题:数据备份和数据体量较大造成的性能降低。这里redis的主从模式为这两个问题提供了一个较好的解决方案。主从模式指的是使用一个redis实例作为主机,其余的实例作为备份机。主机和从机的数据完全一致,主机支持数据的写入和读取等各项操作,而从机则只支持与主机数据的同步和读取,也就是说,客户端可以将数据写入到主机,由主机自动将数据的写入操作同步到从机。主从模式很好的解决了数据备份问题,并且由于主从服务数据几乎是一致的,因而可以将写入数据的命令发送给主机执行,而读取数据的命令发送给不同的从机执行,从而达到读写分离的目的。如下所示主机redis-A分别有redis-B、redis-C、redis-D、redis-E四个从机:

在这里插入图片描述
前面第1点中我们已经介绍了redis单例的配置方式,而上面我们也介绍了主从模式其实也是多个redis实例组成的,因而redis主从模式的配置可以理解为多个不同的redis实例通过一定的配置告知其相互之间的主从关系。

2.2 实战:采用docker-compose
2.2.1 docker和docker-compose都已安装好,并docker已启动且下载好redis镜像。
2.2.2 建立项目目录

总共3个容器

目录结构如下:

— redis-m_s
      — docker-compose.yml
      — master_1_7000
            — conf
                  — redis.conf
            — data
            — logs
      — slave_1_7001
            — conf
                  — redis.conf
            — data
            — logs
      — slave_2_7002
            — conf
                  — redis.conf #redis.conf

2.2.3 编写docker-compose.yml文件
结点IP
master_7000172.16.21.2
slave_1_7001172.16.21.3
slave_2_7002172.16.21.4

docker-compose.yml

version: '3'
services:
    master_7000:
        image: redis
        ports:
            - 7000:6379
        volumes:
            - ./master_7000/conf/redis.conf:/etc/redis/redis.conf
            - ./master_7000/data:/data:rw
            - ./master_7000/logs:/usr/local/redis/logs
        container_name: master_7000
        networks: 
            mynet:
                ipv4_address: 172.16.21.2
        command: redis-server /etc/redis/redis.conf
        restart: always       

    slave_1_7001:
        image: redis
        ports:
            - 7001:6379
        volumes:
            - ./slave_1_7001/conf/redis.conf:/etc/redis/redis.conf
            - ./slave_1_7001/data:/data:rw
            - ./slave_1_7001/logs:/usr/local/redis/logs
        container_name: slave_1_7001
        depends_on:
            - master_7000
        networks: 
            mynet:
                ipv4_address: 172.16.21.3
        command: redis-server /etc/redis/redis.conf
        restart: always

    slave_2_7002:
        image: redis
        ports:
            - 7002:6379
        volumes:
            - ./slave_2_7002/conf/redis.conf:/etc/redis/redis.conf
            - ./slave_2_7002/data:/data:rw
            - ./slave_2_7002/logs:/usr/local/redis/logs
        container_name: slave_2_7002
        depends_on:
            - master_7000
        networks: 
            mynet:
                ipv4_address: 172.16.21.4
        command: redis-server /etc/redis/redis.conf
        restart: always

networks:
    mynet:
        driver: bridge
        ipam:
            driver: default
            config:
                - 
                  subnet: 172.16.21.0/24
                  gateway: 172.16.21.1
2.2.4 修改配置文件redis.conf

redis.conf下载
不设置密码
m_1_7000/conf/redis.conf做如下修改

bind 0.0.0.0 #将绑定ip设置为 0.0.0.0 ,即不绑定ip
protected-mode no # 不设置密码外网访问时需要设置为no
appendonly yes #开启持久化

s_1_7001/conf/redis.conf和s_2_7002/conf/redis.conf做如下修改

bind 0.0.0.0 #将绑定ip设置为 0.0.0.0 ,即不绑定ip
protected-mode no # 不设置密码外网访问时需要设置为no
appendonly yes #开启持久化
slaveof 172.16.21.2 6379

补充
protected-mode yes时,不设置密码只能进行本地连接,设置密码以后可以外网连接。
protected-mode no时,不设置密码也可以外网连接。

设置密码
m_1_7000/conf/redis.conf做如下修改

bind 0.0.0.0 #将绑定ip设置为 0.0.0.0 ,即不绑定ip
protected-mode yes # 外网用密码访问时,最后设置为yes
requirepass 123456 # 作用于主节点,设置主节点认证密码
masterauth 123456  # 作用于从节点,当主结点设置了密码后,从结点复制主节点的数据需要通过该设置,从节点的masterauther设置成于reauirepass相同即可。
appendonly yes #开启持久化

s_1_7001/conf/redis.conf和s_2_7002/conf/redis.conf做如下修改

bind 0.0.0.0 #将绑定ip设置为 0.0.0.0 ,即不绑定ip
protected-mode yes # 外网用密码访问时,最后设置为yes
requirepass 123456 # 作用于主节点,设置主节点认证密码
masterauth 123456  # 作用于从节点,当主结点设置了密码后,从结点复制主节点的数据需要通过该设置,从节点的masterauther设置成于reauirepass相同即可。
appendonly yes #开启持久化
slaveof 172.16.21.2 6379

此处部署使用了密码

2.2.5 启动redis容器

进入redis-m_s目录,执行命令

[root@zhangsan redis-m_s]# docker-compose up -d
Creating network "redis-m_s_mynet" with driver "bridge"
Creating master_7000 ... done
Creating slave_2_7002 ... done
Creating slave_1_7001 ... done
[root@zhangsan redis-m_s]# docker-compose ps
    Name                   Command               State           Ports         
-------------------------------------------------------------------------------
master_7000   docker-entrypoint.sh redis ...   Up      0.0.0.0:7000->6379/tcp
slave_1_7001    docker-entrypoint.sh redis ...   Up      0.0.0.0:7001->6379/tcp
slave_2_7002    docker-entrypoint.sh redis ...   Up      0.0.0.0:7002->6379/tcp
[root@zhangsan redis-m_s]#
2.2.6 测试是否成功

打开一终端进入m_7000 容器

[root@zhangsan redis-m_s]# docker-compose exec master_7000 bash
root@8178035070cb:/data# redis-cli 
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> info replication
# Replication
role:master  # 表明成功
connected_slaves:2  # 表明成功
slave0:ip=172.16.21.4,port=6379,state=online,offset=70,lag=0
slave1:ip=172.16.21.3,port=6379,state=online,offset=70,lag=0
master_replid:7462bff8b1273d8030c45de8d98b8eb0776223fa
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:70
127.0.0.1:6379> 

在这里插入图片描述


3 哨兵模式

3.1 简介

redis主从模式解决了数据备份和单例可能存在的性能问题,但是其也引入了新的问题。由于主从模式配置了三个redis实例,并且每个实例都使用不同的ip(如果在不同的机器上)和端口号,根据前面所述,(1) 主从模式下可以将读写操作分配给不同的实例进行从而达到提高系统吞吐量的目的,但也正是因为这种方式造成了使用上的不便,因为每个客户端连接redis实例的时候都是指定了ip和端口号的,如果所连接的redis实例因为故障下线了,而主从模式也没有提供一定的手段通知客户端另外可连接的客户端地址,因而需要手动更改客户端配置重新连接。另外,(2) 主从模式下,如果主节点由于故障下线了,那么从节点因为没有主节点而同步中断,因而需要人工进行故障转移工作。

为了解决这两个问题,在2.8版本之后redis正式提供了sentinel(哨兵)架构。关于sentinel,这里需要说明几个概念:

名词z逻辑结构物理结构
主节点redis主服务/数据库一个独立的redis进程
从节点redis从服务/数据库一个独立的redis进程
sentinel节点监控redis数据节点一个独立的sentinel进程
sentinel节点集合若干sentinel节点的抽象集合若干sentinel节点进程
应用方泛指一个或多个客户端一个或多个客户端线程或进程

每个sentinel节点其实就是一个redis实例,与主从节点不同的是sentinel节点作用是用于监控redis数据节点的,而sentinel节点集合则表示监控一组主从redis实例多个sentinel监控节点的集合,比如有主节点master和从节点slave-1、slave-2,为了监控这三个主从节点,这里配置N个sentinel节点sentinel-1,sentinel-2,…,sentinel-N。如下图是sentinel监控主从节点的示例图:
在这里插入图片描述
从图中可以看出,对于一组主从节点,sentinel只是在其外部额外添加的一组用于监控作用的redis实例。在主从节点和sentinel节点集合配置好之后,sentinel节点之间会相互发送消息,以检测其余sentinel节点是否正常工作,并且sentinel节点也会向主从节点发送消息,以检测监控的主从节点是否正常工作。

前面讲到,sentinel架构的主要作用是解决主从模式下主节点的故障转移工作的。这里如果主节点因为故障下线,那么某个sentinel节点发送检测消息给主节点时,如果在指定时间内收不到回复,那么该sentinel就会主观的判断该主节点已经下线,那么其会发送消息给其余的sentinel节点,询问其是否“认为”该主节点已下线,其余的sentinel收到消息后也会发送检测消息给主节点,如果其认为该主节点已经下线,那么其会回复向其询问的sentinel节点,告知其也认为主节点已经下线,当该sentinel节点最先收到超过指定数目(配置文件中配置的数目和当前sentinel节点集合数的一半,这里两个数目的较大值)的sentinel节点回复说当前主节点已下线,那么其就会对主节点进行故障转移工作。

故障转移的基本思路是在从节点中选取某个从节点向其发送slaveof no one(假设选取的从节点为127.0.0.1:6380),使其称为独立的节点(也就是新的主节点),然后sentinel向其余的从节点发送slaveof 127.0.0.1 6380命令使它们重新成为新的主节点的从节点。重新分配之后sentinel节点集合还会继续监控已经下线的主节点(假设为127.0.0.1:6379),如果其重新上线,那么sentinel会向其发送slaveof命令,使其成为新的主机点的从节点,如此故障转移工作完成。

上面我们讲到了,每个sentinel节点在本质上还是一个redis实例,只不过和redis数据节点不同的是,其主要作用是监控redis数据节点。需要用到sentinl.conf

3.2 实战:采用docker-compose

目前没有成功,搭建过程中遇到问题为解决。

3.2.1 docker和docker-compose都已安装好,并docker已启动且下载好redis镜像。
3.2.2 建立项目目录

总共6个容器

目录结构如下:

— redis-m_s
      — docker-compose.yml
      — master_7000
            — conf
                  — redis.conf
            — data
            — logs
      — slave_1_7001
            — conf
                  — redis.conf
            — data
            — logs
      — slave_2_7002
            — conf
                  — redis.conf
            — data
            — logs
      — sentinel_1_7003
            — conf
                  — sentinel.conf
            — data
            — logs
      — sentinel_2_7004
            — conf
                  — sentinel.conf
            — data
            — logs
      — sentinel_3_7005
            — conf
                  — sentinel.conf
            — data
            — logs

3.3.3 编写docker-compose.yml文件
version: '3'
services:
    master_7000:
        image: redis
        ports:
            - 7000:6379
        volumes:
            - ./master_7000/conf/redis.conf:/etc/redis/redis.conf
            - ./master_7000/data:/data:rw
            - ./master_7000/logs:/usr/local/redis/logs
        container_name: master_7000
        networks: 
            mynet:
                ipv4_address: 172.16.21.2
        command: redis-server /etc/redis/redis.conf
        # restart: always       
# 注意yaml文件的空行中不能有任何字符包括空格这类空白字符,否则会报错

    slave_1_7001:
        image: redis
        ports:
            - 7001:6379
        volumes:
            - ./slave_1_7001/conf/redis.conf:/etc/redis/redis.conf
            - ./slave_1_7001/data:/data:rw
            - ./slave_1_7001/logs:/usr/local/redis/logs
        container_name: slave_1_7001
        depends_on:
            - master_7000
        networks: 
            mynet:
                ipv4_address: 172.16.21.3
        command: redis-server /etc/redis/redis.conf
        # restart: always

    slave_2_7002:
        image: redis
        ports:
            - 7002:6379
        volumes:
            - ./slave_2_7002/conf/redis.conf:/etc/redis/redis.conf
            - ./slave_2_7002/data:/data:rw
            - ./slave_2_7002/logs:/usr/local/redis/logs
        container_name: slave_2_7002
        depends_on:
            - master_7000
        networks: 
            mynet:
                ipv4_address: 172.16.21.4
        command: redis-server /etc/redis/redis.conf
        # restart: always

    sentinel_1_7003:
        image: redis
        ports: 
            - 7003:26379
        volumes:
            - /sentinel_1_7003/conf/sentinel.conf:/etc/redis/sentinel.conf
            - /sentinel_1_7003/data:/data:rw
            - /sentinel_1_7003/logs:/usr/local/redis/logs
        container_name: sentinel_1_7003
        depends_on:
            - master_7000
            - slave_1_7001
            - slave_2_7002
        networks:
            mynet:
                ipv4_address: 172.16.21.5
        command: redis-sentinel /etc/redis/sentinel.conf
        sysctls:
            net.core.somaxconn: 511
        # restart: always

    sentinel_2_7004:
        image: redis
        ports: 
            - 7004:26379
        volumes:
            - /sentinel_2_7004/conf/sentinel.conf:/etc/redis/sentinel.conf
            - /sentinel_2_7004/data:/data:rw
            - /sentinel_2_7004/logs:/usr/local/redis/logs
        container_name: sentinel_2_7004
        depends_on:
            - master_7000
            - slave_1_7001
            - slave_2_7002
        networks:
            mynet:
                ipv4_address: 172.16.21.6
        command: redis-sentinel /etc/redis/sentinel.conf
        sysctls:
            net.core.somaxconn: 511
        # restart: always

    sentinel_3_7005:
        image: redis
        ports: 
            - 7005:26379
        volumes:
            - /sentinel_3_7005/conf/sentinel.conf:/etc/redis/sentinel.conf
            - /sentinel_3_7005/data:/data:rw
            - /sentinel_3_7005/logs:/usr/local/redis/logs
        container_name: sentinel_3_7005
        depends_on:
            - master_7000
            - slave_1_7001
            - slave_2_7002
        networks:
            mynet:
                ipv4_address: 172.16.21.7
        command: redis-sentinel /etc/redis/sentinel.conf
        sysctls:
            net.core.somaxconn: 511
        # restart:always
        
networks:
    mynet:
        driver: bridge
        ipam:
            driver: default
            config:
                - 
                  subnet: 172.16.21.0/24
                  gateway: 172.16.21.1
3.2.4 修改配置文件redis.conf,sentinel.conf

此处部署使用了密码
master_7000/conf/redis.conf做如下修改

bind 0.0.0.0 #将绑定ip设置为 0.0.0.0 ,即不绑定ip
protected-mode yes # 外网用密码访问时,最后设置为yes
requirepass 123456 # 作用于主节点,设置主节点认证密码
masterauth 123456  # 作用于从节点,当主结点设置了密码后,从结点复制主节点的数据需要通过该设置,从节点的masterauther设置成于reauirepass相同即可。
appendonly yes #开启持久化

slave_1_7001/conf/redis.conf和slave_2_7002/conf/redis.conf做如下修改

bind 0.0.0.0 #将绑定ip设置为 0.0.0.0 ,即不绑定ip
protected-mode yes # 外网用密码访问时,最后设置为yes
requirepass 123456 # 作用于主节点,设置主节点认证密码
masterauth 123456  # 作用于从节点,当主结点设置了密码后,从结点复制主节点的数据需要通过该设置,从节点的masterauther设置成于reauirepass相同即可。
appendonly yes #开启持久化
slaveof 172.16.21.2 6379

sentinel下载
sentinel_1_7003/conf/snetinel.conf
sentinel_2_7004/conf/snetinel.conf
sentinel_3_7005/conf/snetinel.conf
做如下修改

protected-mode yes

bind 0.0.0.0

port 26379

dir "/tmp"

sentinel monitor mymaster 172.16.21.2 6379 2

sentinel down-after-milliseconds mymaster 5000

sentinel failover-timeout mymaster 180000

sentinel parallel-syncs mymaster 1
# 由于主从机都设置了密码,此处也需要设置
sentinel auth-pass mymaster 123456 
配置项参数类型作用
port整数启动哨兵进程端口
dir文件夹目录哨兵进程服务临时文件夹,默认为/tmp,要保证有可写入的权限
sentineldown-after-milliseconds <服务名称><毫秒数(整数)>指定哨兵在监控Redis服务时,当Redis服务在一个默认毫秒数内都无法回答时,单个哨兵认为的主观下线时间,默认为30000(30秒)
sentinelparallel-syncs <服务名称><服务器数(整数)>指定可以有多少个Redis服务同步新的主机,一般而言,这个数字越小同步时间越长,而越大,则对网络资源要求越高
sentinelfailover-timeout <服务名称><毫秒数(整数)>指定故障切换允许的毫秒数,超过这个时间,就认为故障切换失败,默认为3分钟
sentinelnotification-script <服务名称><脚本路径>指定sentinel检测到该监控的redis实例指向的实例异常时,调用的报警脚本。该配置项可选,比较常用

sentinel down-after-milliseconds配置项只是一个哨兵在超过规定时间依旧没有得到响应后,会自己认为主机不可用。对于其他哨兵而言,并不是这样认为。哨兵会记录这个消息,当拥有认为主观下线的哨兵达到sentinel monitor所配置的数量时,就会发起一次投票,进行failover,此时哨兵会重写Redis的哨兵配置文件,以适应新场景的需要。

3.2.5 启动容器
docker-compose up

之后sentinel_1_7003/sentinel_2_7004/sentinel_3_7005报出如下错误,目前没解决。

sentinel_1_7003    | 1:X 09 Dec 2020 02:11:47.048 # Could not rename tmp config file (Is a directory)
sentinel_1_7003    | 1:X 09 Dec 2020 02:11:47.049 # WARNING: Sentinel was not able to save the new configuration on disk!!!: Is a directory

sentinel_2_7004    | 1:X 09 Dec 2020 02:11:47.333 # Could not rename tmp config file (Is a directory)
sentinel_2_7004    | 1:X 09 Dec 2020 02:11:47.334 # WARNING: Sentinel was not able to save the new configuration on disk!!!: Is a directory


sentinel_3_7005    | 1:X 09 Dec 2020 02:11:47.277 # Could not rename tmp config file (Is a directory)
sentinel_3_7005    | 1:X 09 Dec 2020 02:11:47.277 # WARNING: Sentinel was not able to save the new configuration on disk!!!: Is a directory

目前没有解决该问题


4 集群模式

4.0 简介

redis集群是在redis 3.0版本推出的一个功能,其有效的解决了redis在分布式方面的需求。(1) 当遇到单机内存,并发和流量瓶颈等问题时,可采用Cluster方案达到负载均衡的目的。(2) redis中sentinel有效的解决了故障转移的问题,也解决了主节点下线客户端无法识别新的可用节点的问题,但是如果是从节点下线了,sentinel是不会对其进行故障转移的,并且连接从节点的客户端也无法获取到新的可用从节点,而这些问题在Cluster中都得到了有效的解决。

redis集群中数据是和槽(slot)挂钩的,其总共定义了6384个槽,所有的数据根据一致哈希算法会被映射到这16384个槽中的某个槽中;另一方面,这16384个槽是按照设置被分配到不同的redis节点上的,比如启动了三个redis实例:cluster-A,cluster-B和cluster-C,这里将0-5460号槽分配给cluster-A,将5461-10922号槽分配给cluster-B,将10923-16383号槽分配给cluster-C(总共有16384个槽,但是其标号类似数组下标,是从0到16383)。也就是说数据的存储只和槽有关,并且槽的数量是一定的,由于一致hash算法是一定的,因而将这16384个槽分配给无论多少个redis实例,对于确认的数据其都将被分配到确定的槽位上。redis集群通过这种方式来达到redis的高效和高可用性目的。

这里需要进行说明的一点是,一致哈希算法根据数据的key值计算映射位置时和所使用的节点数量有非常大的关系。一致哈希分区的实现思路是为系统中每个节点分配一个token,范围一般在0~2^32,这些token构成一个哈希环,数据读写执行节点查找操作时,先根据key计算hash值,然后顺时针找到第一个大于等于该hash值的token节点,需要操作的数据就保存在该节点上。通过分析可以发现,一致哈希分区存在如下问题:

  • 加减节点会造成哈希环中部分数据无法命中,需要手动处理或忽略这部分数据;
  • 当使用少量节点时,节点变化将大范围影响环中数据映射,因此这种方式不适合少量节点的分布式方案;
  • 普通的一致性哈希分区在增减节点时需要增加一倍或减去一半节点才能保证数据和负载的平衡。

正是由于一致哈希分区的这些问题,redis使用了虚拟槽来处理分区时节点变化的问题,也即将所有的数据映射到16384个虚拟槽位上,当redis节点变化时数据映射的槽位将不会变化,并且这也是redis进行节点扩张的基础。

4.1 Redis集群设计原理

Redis集群设计包括2部分:哈希Slot和节点主从,本篇博文通过3张图来搞明白Redis的集群设计。

节点主从:

主从设计不算什么新鲜玩意,在数据库中我们也经常用主从来做读写分离,直接上图:
在这里插入图片描述
图上能看得到的信息:

  1. 只有1个Master,可以有N个slaver,而且Slaver也可以有自己的Slaver,由于这种主从的关系决定他们是在配置阶段就要指定他们的上下级关系,而不是Zookeeper那种平行关系是自主推优出来的。
  2. 读写分离,Master只负责写和同步数据给Slaver,Slaver承担了被读的任务,所以Slaver的扩容只能提高读效率不能提高写效率。
  3. Slaver先将Master那边获取到的信息压入磁盘,再load进内存,client端是从内存中读取信息的,所以Redis是内存数据库。

当一个新的Slaver加入到这个集群时,会主动找Master来拜码头,Master发现新的小弟后将全量数据发送给新的Slaver,数据量越大性能消耗也就越大,所以尽量避免在运行时做Slaver的扩容。

简单总结下主从模式的设计:

  • 优点:读写分离,通过增加Slaver可以提高并发读的能力。
  • 缺点:Master写能力是瓶颈。
    • 虽然理论上对Slaver没有限制但是维护Slaver开销总将会变成瓶颈。
    • Master的Disk大小也将会成为整个Redis集群存储容量的瓶颈。
哈希Slot:

这个艺名看起来很文艺,但也不是什么新技术,他的真名就叫分表分库,再上一个图:
在这里插入图片描述图上能看到的信息:

  1. 对象保存到Redis之前先经过CRC16哈希到一个指定的Node上,例如Object4最终Hash到了Node1上。
  2. 每个Node被平均分配了一个Slot段,对应着0-16384,Slot不能重复也不能缺失,否则会导致对象重复存储或无法存储。
  3. Node之间也互相监听,一旦有Node退出或者加入,会按照Slot为单位做数据的迁移。例如Node1如果掉线了,0-5640这些Slot将会平均分摊到Node2和Node3上,由于Node2和Node3本身维护的Slot还会在自己身上不会被重新分配,所以迁移过程中不会影响到5641-16384Slot段的使用。

简单总结下哈希Slot的优缺点:

  • 缺点:每个Node承担着互相监听、高并发数据写入、高并发数据读出,工作任务繁重
  • 优点:将Redis的写操作分摊到了多个节点上,提高写的并发能力,扩容简单。
双剑合并:

看到这里大家也就发现了,主从和哈希的设计优缺点正好是相互弥补的,将图一每一套主从对应到图二中的每一个Node,就是Redis集群的终极形态,先Hash分逻辑节点,然后每个逻辑节点内部是主从,如图:
在这里插入图片描述
想扩展并发读就添加Slaver,想扩展并发写就添加Master,想扩容也就是添加Master,任何一个Slaver或者几个Master挂了都不会是灾难性的故障。

三张图秒懂Redis集群设计原理

4.2 redis slot 槽点

Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value
时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

Redis 集群没有使用一致性hash, 而是引入了哈希槽的概念。

Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽。这种结构很容易添加或者删除节点,并且无论是添加删除或者修改某一个节点,都不会造成集群不可用的状态。

使用哈希槽的好处就在于可以方便的添加或移除节点。

当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了;

当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就行了;

在这一点上,我们以后新增或移除节点的时候不用先停掉所有的 redis 服务。

"用了哈希槽的概念,而没有用一致性哈希算法,不都是哈希么?这样做的原因是为什么呢?"

Redis Cluster是自己做的crc16的简单hash算法,没有用一致性hash。Redis的作者认为它的crc16(key) mod 16384的效果已经不错了,虽然没有一致性hash灵活,但实现很简单,节点增删时处理起来也很方便。

"为了动态增删节点的时候,不至于丢失数据么?"
节点增删时不丢失数据和hash算法没什么关系,不丢失数据要求的是一份数据有多个副本。

“还有集群总共有2的14次方,16384个哈希槽,那么每一个哈希槽中存的key 和 value是什么?”

当你往Redis Cluster中加入一个Key时,会根据crc16(key) mod 16384计算这个key应该分布到哪个hash slot中,一个hash slot中会有很多key和value。你可以理解成表的分区,使用单节点时的redis时只有一个表,所有的key都放在这个表里;改用Redis Cluster以后会自动为你生成16384个分区表,你insert数据时会根据上面的简单算法来决定你的key应该存在哪个分区,每个分区里有很多key。

redis slot 槽点

4.3 实战:在单机Docker中搭建高可用redis集群
4.3.1 docker和docker-compose都已安装好,并docker已启动且下载好redis镜像。
4.3.2 建立项目目录

总共6个容器

目录结构如下:

— redis-cluster
      — docker-compose.yml
      — m_1_7000
            — conf
                  — redis.conf
            — data
            — logs
      — m_2_7001
            — conf
                  — redis.conf
            — data
            — logs
      — m_3_7002
            — conf
                  — redis.conf
            — data
            — logs
      — s_11_7003
            — conf
                  — redis.conf
            — data
            — logs
      — s_21_7004
            — conf
                  — redis.conf
            — data
            — logs
      — s_31_7005
            — conf
                  — redis.conf
            — data
            — logs

4.3.3 编写docker-compose.yml文件

此处没有配指定的网络,没有为每个容器配指定的ip,当然你也可以指定。此处docker为redis-cluster_mynet自动分配一个网络号,为每个容器自动分配ip。

version: '3'
services:
    m_1_7000:
        image: redis
        ports:
            - 7000:6379
        volumes:
            - ./m_1_7000/conf/redis.conf:/etc/redis/redis.conf
            - ./m_1_7000/data:/data:rw
            - ./m_1_7000/logs:/usr/local/redis/logs
        container_name: m_1_7000
        networks: 
            - mynet
        command: redis-server /etc/redis/redis.conf
        restart: always       

    m_2_7001:
        image: redis
        ports:
            - 7001:6379
        volumes:
            - ./m_2_7001/conf/redis.conf:/etc/redis/redis.conf
            - ./m_2_7001/data:/data:rw
            - ./m_2_7001/logs:/usr/local/redis/logs
        container_name: m_2_7001
        networks: 
            - mynet
        command: redis-server /etc/redis/redis.conf
        restart: always

    m_3_7002:
        image: redis
        ports:
            - 7002:6379
        volumes:
            - ./m_3_7002/conf/redis.conf:/etc/redis/redis.conf
            - ./m_3_7002/data:/data:rw
            - ./m_3_7002/logs:/usr/local/redis/logs
        container_name: m_3_7002
        networks: 
            - mynet
        command: redis-server /etc/redis/redis.conf
        restart: always

    s_11_7003:
        image: redis
        ports:
            - 7003:6379
        volumes:
            - ./s_11_7003/conf/redis.conf:/etc/redis/redis.conf
            - ./s_11_7003/data:/data:rw
            - ./s_11_7003/logs:/usr/local/redis/logs
        container_name: s_11_7003
        depends_on:
            - m_1_7000
        networks: 
            - mynet
        command: redis-server /etc/redis/redis.conf
        restart: always

    s_21_7004:
        image: redis
        ports:
            - 7004:6379
        volumes:
            - ./s_21_7004/conf/redis.conf:/etc/redis/redis.conf
            - ./s_21_7004/data:/data:rw
            - ./s_21_7004/logs:/usr/local/redis/logs
        container_name: s_21_7004
        depends_on:
            - m_2_7001
        networks: 
            - mynet
        command: redis-server /etc/redis/redis.conf
        restart: always

    s_31_7005:
        image: redis
        ports:
            - 7005:6379
        volumes:
            - ./s_31_7005/conf/redis.conf:/etc/redis/redis.conf
            - ./s_31_7005/data:/data:rw
            - ./s_31_7005/logs:/usr/local/redis/logs
        container_name: s_31_7005
        depends_on:
            - m_3_7002
        networks: 
            - mynet
        command: redis-server /etc/redis/redis.conf
        restart: always

networks:
    mynet:  # 启动容器后会生成一个redis-cluster_mynet的网络
        driver: bridge
4.3.4 修改配置文件redis.conf

redis.conf下载
不设置密码

bind 0.0.0.0 #将绑定ip设置为 0.0.0.0 ,即不绑定ip
protected-mode no # 不设置密码外网访问时需要设置为no
appendonly yes #开启持久化
cluster-enabled yes #开启集群
cluster-config-file nodes.conf #集群配置文件(这个在后面搭建的时候,会自动生成,不用管,这样写就对了)
cluster-node-timeout 15000 #节点超时时间

补充
protected-mode yes时,不设置密码只能进行本地连接,设置密码以后可以外网连接。
protected-mode no时,不设置密码也可以外网连接。

设置密码

bind 0.0.0.0 #将绑定ip设置为 0.0.0.0 ,即不绑定ip
protected-mode yes # 外网用密码访问时,最后设置为yes
requirepass 123456 # 设置连接认证密码
masterauth 123456  # 主从复制的验证密码
appendonly yes #开启持久化
cluster-enabled yes #开启集群
cluster-config-file nodes.conf #集群配置文件(这个在后面搭建的时候,会自动生成,不用管,这样写就对了)
cluster-node-timeout 15000 #节点超时时间
4.3.5 启动redis容器

进入redis-cluster目录,执行命令

[root@zhangsan redis-cluster]# docker-compose up -d
Creating network "redis-cluster_mynet" with driver "bridge"
Creating m_1_7000  ... done
Creating m_3_7002  ... done
Creating m_2_7001 ... done
Creating s_21_7004 ... done
Creating s_11_7003 ... done
Creating s_31_7005 ... done
(base) [root@zhansan redis-cluster]# docker-compose ps
  Name                 Command               State           Ports         
---------------------------------------------------------------------------
m_1_7000    docker-entrypoint.sh redis ...   Up      0.0.0.0:7000->6379/tcp
m_2_7001    docker-entrypoint.sh redis ...   Up      0.0.0.0:7001->6379/tcp
m_3_7002    docker-entrypoint.sh redis ...   Up      0.0.0.0:7002->6379/tcp
s_11_7003   docker-entrypoint.sh redis ...   Up      0.0.0.0:7003->6379/tcp
s_21_7004   docker-entrypoint.sh redis ...   Up      0.0.0.0:7004->6379/tcp
s_31_7005   docker-entrypoint.sh redis ...   Up      0.0.0.0:7005->6379/tcp

4.3.6 将每个redis容器加入集群
4.3.6.1 查看每个容器的ip
[root@zhansan redis-cluster]# docker network ls
NETWORK ID          NAME                  DRIVER              SCOPE
7fcfe5724a97        bridge                bridge              local
6f4636b11f66        host                  host                local
8d9534bd24c4        none                  null                local
a2e10a970796        redis-cluster_mynet   bridge              local  # NAME=项目名+'_'+docker-compose.yml中为每个容器定义的networks名
[root@zhangsan redis-cluster]# docker network inspect redis-cluster_mynet
[
    {
        "Name": "redis-cluster_mynet",
        "Id": "a2e10a970796d79be7a15b42338afeac0f925edbe2f2f8d3d716bb4cb6d3573d",
        "Created": "2020-12-06T22:27:43.387866792+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.22.0.0/16",
                    "Gateway": "172.22.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "59bd72b1505255fa41b23fcf590a0dc44273efc07ceaaf9eba2ea7a6f97ca403": {
                "Name": "m_1_7000",
                "EndpointID": "e3bf5f8259bd7630fec1fa1dfa0b06406f2857bacca3d6a92f90e9be358e41ec",
                "MacAddress": "02:42:ac:16:00:04",
                "IPv4Address": "172.22.0.4/16",
                "IPv6Address": ""
            },
            "6c32877857f75fca90287a8ae157f7fd209c03d532d0b1627eaa8e9d4dd11fbd": {
                "Name": "m_2_7001",
                "EndpointID": "38a5b3d0208a54bea19863bea64d7e3cf015fc4b2adfa1ccf75830ce7e321b75",
                "MacAddress": "02:42:ac:16:00:03",
                "IPv4Address": "172.22.0.3/16",
                "IPv6Address": ""
            },
            "80b638f43deb4f0fce6b5ed81250486cd86b0828ff4e6d581c367fbcbce8559f": {
                "Name": "m_3_7002",
                "EndpointID": "e3a93b36d70d578b50e82b68332930686e6050f1be30bd349f00411b9bc1edba",
                "MacAddress": "02:42:ac:16:00:02",
                "IPv4Address": "172.22.0.2/16",
                "IPv6Address": ""
            },
            "9624fc9a8cef195b1eb36e0ee23f01a3662598d165fae8062fe812060ebb08d3": {
                "Name": "s_11_7003",
                "EndpointID": "c7a2655c7c325e9c32dcfb81a890be258a5cec4a3cd77f6232d7d51b753099d2",
                "MacAddress": "02:42:ac:16:00:07",
                "IPv4Address": "172.22.0.7/16",
                "IPv6Address": ""
            },
            "b6eb9047f15416169e550e9093401a899d36203d8fed27253a048579a5208d12": {
                "Name": "s_31_7005",
                "EndpointID": "c98652209a1c3493793aab5640570f56410cbe1922c118686ff40f8aa7147ea0",
                "MacAddress": "02:42:ac:16:00:05",
                "IPv4Address": "172.22.0.5/16",
                "IPv6Address": ""
            },
            "ca55bcde0d54759cc1e68fb10ccc69e1ada33ae69511e50647d949798a2a5433": {
                "Name": "s_21_7004",
                "EndpointID": "82d708dd294ef1bfc18869b0fa45b7567c22329a91a0056a3c3485d980c7d001",
                "MacAddress": "02:42:ac:16:00:06",
                "IPv4Address": "172.22.0.6/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "mynet",
            "com.docker.compose.project": "redis-cluster",
            "com.docker.compose.version": "1.27.4"
        }
    }
]

把Containers 里面内容的 Name 和 IPv4Address 保存下来,并分配好主从关系,后面要用到

主(master)从(slave)
m_1_7000 : 172.22.0.4s_11_7003 : 172.22.0.7
m_2_7001 : 172.22.0.3s_21_7004 : 172.22.0.6
m_3_7002 : 172.22.0.2s_31_7005 : 172.22.0.5
4.3.6.2 将每个容器加入集群

随意进入一个redis容器,此处进的时m_1_7000容器

(base) [root@zhangsan redis-cluster]# docker-compose exec m_1_7000 bash
root@caa2e951b5a3:/data# redis-cli 
127.0.0.1:6379> auth 123456  #若没有设置密码则忽略该步
OK
127.0.0.1:6379> cluster meet 172.22.0.4 6379
OK
127.0.0.1:6379> cluster meet 172.22.0.3 6379
OK
127.0.0.1:6379> cluster meet 172.22.0.2 6379
OK
127.0.0.1:6379> cluster meet 172.22.0.7 6379
OK
127.0.0.1:6379> cluster meet 172.22.0.6 6379
OK
127.0.0.1:6379> cluster meet 172.22.0.5 6379
OK
127.0.0.1:6379> cluster nodes
3bcab93b86f8c342c6529f2ca743ded1622adfaf 172.22.0.4:6379@16379 myself,master - 0 1607265252000 1 connected
476a42c2d8dd674edf4944d230168bbaa792bdc2 172.22.0.5:6379@16379 master - 0 1607265253834 5 connected
15ecd4b97008980f9078a062b3be469ab45f14ef 172.22.0.2:6379@16379 master - 0 1607265251829 2 connected
859d7fda69c450ea74d9aba3eddc01e8be196e4d 172.22.0.3:6379@16379 master - 0 1607265250000 0 connected
1641f92a3d805b9c46e19fe1607b54d9a1b5a225 172.22.0.6:6379@16379 master - 0 1607265251000 4 connected
3045226eb57977e2d242eaff7d8ce965890d2624 172.22.0.7:6379@16379 master - 0 1607265252831 3 connected
127.0.0.1:6379> 

现在,我们要记录 3 个 主 master 的 节点标识,配置主从结构时要用到

主(mashter)标识
m_1_7000 : 172.22.0.43bcab93b86f8c342c6529f2ca743ded1622adfaf
m_2_7001 : 172.22.0.3859d7fda69c450ea74d9aba3eddc01e8be196e4d
m_3_7002 : 172.22.0.215ecd4b97008980f9078a062b3be469ab45f14ef
4.3.7 配置槽点

编写脚本

[root@zhangsan redis-cluster]# vim addslots.sh
[root@zhangsan redis-cluster]# mv addslots.sh > m_1_7000/data/addslots.sh
[root@zhangsan redis-cluster]# chmod 755 m_1_7000/data/addslots.sh

addslots.sh文件内容

#!/bin/bash

# 将0-5461的槽点配置在 m_1_7000 上
n=0
for ((i=n;i<=5461;i++))
do 
    # (1) 若没有设置密码需要去掉'-a 123465'
    # (2) 因为本地没有安装redis,也就没有redis-cli客户端,因此需要到某个redis容器中使用redis-cli,所以相当于在redis-cluster_mynet中一个容器访问其他容器,所以-h设置为不同容器ip,而-p设置为6379,当然也可以不用设置-p,因为-p默认就是6379。
    # 如果本地安装了reids,有redis-cli,也可以在本地执行该脚本,不过-h需要设置为127.0.0.1,-p 设置为 7000、7001、7002.
    # (3) 2>/dev/null。当设置了密码时,没有2>/dev/null,执行脚本会输出'Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.'这样的警告信息,导致脚本不能继续执行下去。因此需要添加 2>/dev/null ,去掉警告。
    redis-cli -h 172.22.0.4 -p 6379 -a 123456  cluster addslots ${i} 2>/dev/null
done

# 将5462-10922的槽点配置在 m_2_7001 上
n=5462
for ((i=n;i<=10922;i++))
do 
    # 若没有设置密码需要去掉'-a 123465'
    redis-cli -h 172.22.0.2 -p 6379 -a 123456 cluster addslots ${i} 2>/dev/null 
done

# 将10923-16383的槽点配置在 m_3_7002 上
n=10923
for ((i=n;i<=16383;i++))
do 
    # 若没有设置密码需要去掉'-a 123465'
    redis-cli -h 172.22.0.3 -p 6379 -a 123456  cluster addslots ${i} 2>/dev/null
done

再次进入m_1_7000容器,然后执行 addslots.sh 文件,分配槽点

[root@zhangsan redis-cluster]#docker-compose exec m_1_7000 bash
root@59bd72b15052:/data# ./addslots.sh
OK
OK
.
.
.
root@59bd72b15052:/data#
4.3.8 配置主从结构

编写脚本

[root@zhangsan redis-cluster]# vim slaves.sh
[root@zhangsan redis-cluster]# mv slaves.sh > m_1_7000/data/slaves.sh
[root@zhangsan redis-cluster]# chmod 755 m_1_7000/data/slaves.sh

slaves.sh文件内容

# 需要用到 从redis 的IP 与 主redis 的节点标识

# 主 redis1 从 redis4
# 对于 -h -p -a 2>/dev/null 的设置与addslots.sh的情况相同。
redis-cli -h 172.22.0.7 -p 6379 -a 123456 CLUSTER REPLICATE 3bcab93b86f8c342c6529f2ca743ded1622adfaf 2>/dev/null

# 主 redis2 从 redis5
redis-cli -h 172.22.0.6 -p 6379 -a 123456 CLUSTER REPLICATE 859d7fda69c450ea74d9aba3eddc01e8be196e4d 2>/dev/null

# 主 redis3 从 redis6
redis-cli -h 172.22.0.5 -p 6379 -a 123456 CLUSTER REPLICATE 15ecd4b97008980f9078a062b3be469ab45f14ef 2>/dev/null

再次进入m_1_7000容器,然后执行 addslots.sh 文件,配置主从结构

[root@zhangsan redis-cluster]#docker-compose exec m_1_7000 bash
root@59bd72b15052:/data# ./slaves.sh
OK
OK
OK
root@59bd72b15052:/data# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> cluster nodes
3bcab93b86f8c342c6529f2ca743ded1622adfaf 172.22.0.4:6379@16379 myself,master - 0 1607308632000 1 connected 0-5461
476a42c2d8dd674edf4944d230168bbaa792bdc2 172.22.0.5:6379@16379 slave 15ecd4b97008980f9078a062b3be469ab45f14ef 0 1607308633922 2 connected
15ecd4b97008980f9078a062b3be469ab45f14ef 172.22.0.2:6379@16379 master - 0 1607308633000 2 connected 10923-16383
859d7fda69c450ea74d9aba3eddc01e8be196e4d 172.22.0.3:6379@16379 master - 0 1607308631913 0 connected 5462-10922
1641f92a3d805b9c46e19fe1607b54d9a1b5a225 172.22.0.6:6379@16379 slave 859d7fda69c450ea74d9aba3eddc01e8be196e4d 0 1607308632916 0 connected
3045226eb57977e2d242eaff7d8ce965890d2624 172.22.0.7:6379@16379 slave 3bcab93b86f8c342c6529f2ca743ded1622adfaf 0 1607308634925 1 connected
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5
cluster_my_epoch:1
cluster_stats_messages_ping_sent:43474
cluster_stats_messages_pong_sent:44261
cluster_stats_messages_meet_sent:6
cluster_stats_messages_sent:87741
cluster_stats_messages_ping_received:44260
cluster_stats_messages_pong_received:43480
cluster_stats_messages_meet_received:1
cluster_stats_messages_received:87741
127.0.0.1:6379> 

配置完以后主从关系关联表(左边为主,对应右边为从)

主redis(容器)主redis(宿主)从redis(容器)从redis(宿主)
m_1_7000 - 172.22.0.4:6379127.0.0.1:7000s_11_7003 - 172.22.0.7:6379127.0.0.1:7003
m_2_7001 - 172.22.0.3:6379127.0.0.1: 7001s_21_7004 -172.22.0.6:6379127.0.0.1:7004
m_3_7002 - 172.22.0.2:6379127.0.0.1:7002s_31_7005 - 172.22.0.5:6379127.0.0.1:7005

当某个主节点崩掉时,它的从节点可以替补转为主节点。并且当崩掉的主节点恢复时,它只能变为从节点,也就是主从地位发生了反转。

4.3.9 测试是否成功

打开一个终端进入m_1_7000 容器

[root@zhangsan redis-cluster]# docker-compose exec m_1_7000 bash
root@59bd72b15052:/data# redis-cli -h 172.22.0.3 -p 6379 -c   # 以集群方式进入m_2_7001    
172.22.0.3:6379> auth 123456
OK
172.22.0.3:6379> set name zhangsan
OK
172.22.0.3:6379> get name
"zhangsan"
172.22.0.3:6379> 

如果不以集群的方式(-c)进入 redis 会出现错误
打开另一个终端进入s_11_7003 容器

[root@zhangsan redis-cluster]# docker-compose exec s_11_7003 bash
root@9624fc9a8cef:/data# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get name
(error) MOVED 5798 172.22.0.3:6379  # 没有以集群方式进入会报该错
127.0.0.1:6379> exit
root@9624fc9a8cef:/data# redis-cli -c # 重新以集群方式进入
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get name
-> Redirected to slot [5798] located at 172.22.0.3:6379
(error) NOAUTH Authentication required.  # 目前不知原因,重试了一次成功
172.22.0.3:6379> auth 123456
OK
172.22.0.3:6379> get name
"zhangsan"
172.22.0.3:6379> 
4.3.10 补充

以下命令是Redis Cluster集群所独有的,执行下面命令需要先登录redis:

集群

cluster info :打印集群的信息
cluster nodes :列出集群当前已知的所有节点( node),以及这些节点的相关信息。

节点

cluster meet <ip> <port> :将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
cluster forget <node_id> :从集群中移除 node_id 指定的节点。
cluster replicate <master_node_id> :将当前从节点设置为 node_id 指定的master节点的slave节点。只能针对slave节点操作。
cluster saveconfig :将节点的配置文件保存到硬盘里面。

槽(slot)

cluster addslots <slot> [slot ...]:将一个或多个槽( slot)指派( assign)给当前节点。
cluster delslots <slot> [slot ...]:移除一个或多个槽对当前节点的指派。
cluster flushslots:移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
cluster setslot <slot> node <node_id>:将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给
另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
cluster setslot <slot> migrating <node_id> :将本节点的槽 slot 迁移到 node_id 指定的节点中。
cluster setslot <slot> importing <node_id> :从 node_id 指定的节点中导入槽 slot 到本节点。
cluster setslot <slot> stable:取消对槽 slot 的导入( import)或者迁移( migrate)。

cluster keyslot <key>:计算键 key 应该被放置在哪个槽上。
cluster countkeysinslot <slot>:返回槽 slot 目前包含的键值对数量。
cluster getkeysinslot <slot> <count> :返回 count 个 slot 槽中的键 。


5 使用docker集群部署redis集群

如果需要更高的性能的redis集群,需要使用跨机的docker集群,也就是要用到docker-machine和docker-swarm。


[参考博客]
docker配置Redis哨兵Sentinel模式
redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比
Redis Cluster日常操作命令梳理

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值