https://www.huangdf.xyz/categories/study-notes
南风
南风
发布于 2025-07-30 / 13 阅读
1
0

容器化部署Redis

1、redis基本信息

redis是一种基于内存的非关系型数据库,具有高性能、支持多种数据结构、可持久化、复制、集群、以及发布订阅等特点。

基于内存使得redis的读写性能非常强大。其所支持的数据结构包括字符串、哈希、列表、集合、有序集合等。持久化方面,redis支持快照和AOF。复制方面redis除了单机模式还支持主从复制、烧饼集群、cluster集群等,可以实现数据的备份和高可用。此外,redis还可以作为消息队列使用,他所支持的数据结构中的列表,可以通过pop()和push()等操作,实现数据的有序进出从而达到消息队列的效果。遇到性能瓶颈还可以通过集群等方式增加性能。

1.1、基本数据结构

string:redis最基本的数据结构。是二进制安全的,在c语言中,是以\0来判断字符串是否结束,而redis存储字符串是通过SDS封装,在存储的时候会存储长度、内容、已使用空间三个参数,因此不需要对存储的字符串进行判断,即使存储的字符串中包含了\0也不会被认定为字符串结束的标志,因此是二进制安全的。string这个数据结构多用来存放token、验证码等信息,可以通过设定过期时间实现到期删除以及通过刷新过期时间实现持续使用token不过期等操作。

list:可以用来存放有多个序的字符串,并按照特定顺序取出,从而实现栈和队列的效果。该数据结构的api包括lpush()、lpop()、rpush()、rpop(),分别表示左进、左出、右进、右出。同侧进出相当于是栈,异侧进出相当于是队列,因此这个结构也能用来做消息队列,将消息放入列表中,再从另一侧取出,从而实现顺序消费,消费失败还能再放回去,或者重试几次放入另一个列表,实现死信队列。(下图以abc为顺序插入)

hash:hash是一种存储键值对的map数据结构,适合用来存放对象类数据。每一个键都是唯一的,当遇到重复的键时会报告同名键值已存在。(不同的对象通过键名区别,键下面通过key取到数据)

set:无序不重复集合。和list相比set能够保证插入的顺序,但无法保证取出的顺序。在存取方面set提供了随机取出这个操作,也对数据的写入做了去重处理,保证了数据的唯一性。使用场景可以是标签类,比如视频的多个同名标签只算一个,或者商品品类不能重复等等。(数据不重复,但是相应的取出的顺序没办法保证)

zset:有序set。顺序是依托于score这个属性。在set的基础上,zset将值改为了score,通过score对zset中的数据进行排序。zset这个数据结构可以用来做排行榜、点击量或者热度榜等功能,当出现同名value时,会覆盖掉原来的score,通过修改score的值,实现排行榜、阅读量等数据的修改等操作(默认是升序排序)

2、容器化部署

在很多源被墙了的环境下,镜像的拉取变得困难。这里提供一个方法。

首先在 Docker Hub Container Image Library | App Containerization 查询想要拉取的镜像的版本,搜索框搜索就行,然后复制这个镜像的名称即可。例如apache/kafka:4.0.1-rc0。

然后在github上,查找一个叫做DockerTarBuilder的项目,这是一个工作流,可以拉取镜像并存储在Artifact文件或Release文件。操作的步骤仓库里面有,这里就不赘述。

2.1、单机部署

默认已经拉取好了镜像。

这里是通过docker compose启动,如何安装compose不赘述,主场还是redis。

2.1.1、配置文件

redis.conf

requirepass "this is your password"

基本上都是默认的,持久化方式、持久化频率需要的话可以改一改,端口也一样,不喜欢6379可以改了。如果想redis安全一些,还可以设置密码。

2.1.2、compose文件

docker-compose.yml

version: '3.0'
services:
  master:
    image: redis:latest
    container_name: redis-master
    ports:
      - 6379:6379
    command: redis-server /usr/local/etc/redis/redis.conf
    privileged: true
    volumes:
      - ./redis_master/conf:/usr/local/etc/redis
      - ./redis_master/data:/data

规定了端口的映射,挂载了配置文件和data目录,防止删除容器数据消失。

然后通过docker-compose up -d就可以后台启动一个端口为6379的redis容器了。

不加-d,就是前台运行,关闭页面服务也就停止了,但是可以用来看运行日志。

2.2、哨兵集群

哨兵模式下需要启动三个redis节点,一主双从,以及三个哨兵节点。redis节点负责数据的读写,哨兵节点负责故障转移以确保服务的高可用。

三个redis节点,主节点负责读写,从节点负责读以及同步。当主节点宕机之后,通过哨兵选举出新的主节点,原来的主节点上线后自动成为从节点。

哨兵会和redis节点维持心跳连接,当超过一定时间没有对ping命令进行回复或者回复错误,则该哨兵节点认为该redis节点下线,这是基于单个哨兵节点的判断,因此称为主观下线SDOWN(Subjectively Down)。

此外还有客观下线,即当多个哨兵节点都主观下线某个redis节点,并通过SENTINEL is-master-down-by-addr命令互相交流确认后,共同认为该节点已经下线,这是基于哨兵节点的共识,因此称为客观下线ODOWN(Objectively Down)。

当一个节点被一个哨兵标记为主观下线后还需要经过其他节点的认可才会被标记为客观下线。

2.2.1、配置文件

redis.conf:基本上都是一样的,需要修改的内容只有端口以及从属于那个节点。

主节点:基本上就这几个需要注意,别的默认即可,持久化方式及频率同单机模式。

port 6379
requirepass "redispass"
masterauth "redispass"

从节点:

port 6380/6381
requirepass "redispass"
masterauth "redispass"
replicaof master_ip master_port

需要规定好是从属于那个主节点,端口和ip需要根据实际修改。

sentinel.conf:哨兵配置文件,需要处理的只有端口和redis节点的密码,别的默认也是可以的

port 26379/26380/26381
daemonize no
sentinel monitor redis-master mastermaster_ip master_port 2
sentinel deny-scripts-reconfig yes
sentinel auth-pass redis-master yourredispassword

monitor这个配置项是定义主节点是谁,redis-master可以自定义名称,需要和下面的保持一致。ip是主节点的ip,port是对应的端口。2表示需要两个及以上哨兵认同才能当选主节点。

其余的默认就行,想自己设置也是可以的。

2.2.2、compose文件

这里选择是一次性启动全部的容器,所以只有一个compose文件。

version: '3.0'
services:
  master:
    image: redis:latest
    container_name: redis-master
    ports:
      - port:port
    command: redis-server /usr/local/etc/redis/redis.conf
    privileged: true
    volumes:
      - ./redis_master/conf:/usr/local/etc/redis
      - ./redis_master/data:/data
    networks:
      redisnetwork:
        ipv4_address: your_ip
 
  slave1:
    image: redis:latest
    container_name: redis-slave-1
    ports:
      - port:port
    command: redis-server /usr/local/etc/redis/redis.conf
    privileged: true
    volumes:
      - ./redis_slave_1/conf:/usr/local/etc/redis
      - ./redis_slave_1/data:/data
    depends_on:
      - master
    networks:
      redisnetwork:
        ipv4_address: your_ip

  slave2:
    image: redis:latest
    container_name: redis-slave-2
    ports:
      - port:port
    command: redis-server /usr/local/etc/redis/redis.conf
    privileged: true
    volumes:
      - ./redis_slave_2/conf:/usr/local/etc/redis
      - ./redis_slave_2/data:/data
    networks:
      redisnetwork:
        ipv4_address: your_ip
    depends_on:
      - master


  sentinel1:
    image: redis:latest
    container_name: redis-sentinel-1
    ports:
      - port:port
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    networks:
      redisnetwork:
        ipv4_address: your_ip
    privileged: true
    volumes:
      - ./sentinel1/conf:/usr/local/etc/redis
      - ./sentinel1/data:/data
    depends_on:
      - master
      - slave1
      - slave2


  sentinel2:
    image: redis:latest
    container_name: redis-sentinel-2
    ports:
      - port:port
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    privileged: true
    volumes:
      - ./sentinel2/conf:/usr/local/etc/redis
      - ./sentinel2:/data:/data
    networks:
      redisnetwork:
        ipv4_address: your_ip
    depends_on:
      - master
      - slave1
      - slave2


  sentinel3:
    image: redis:latest
    container_name: redis-sentinel-3
    ports:
      - port:port
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    privileged: true
    volumes:
      - ./sentinel3/conf:/usr/local/etc/redis
      - ./sentinel3/data:/data
    networks:
      redisnetwork:
        ipv4_address: your_ip
    depends_on:
      - master
      - slave1
      - slave2

networks:
  redisnetwork:
    external: true
    driver: bridge
    ipam:
      config:
        - subnet: "your_subnet"
          gateway: "your_gateway"

因为一些原因,博客不能出现ip,所以这里把ip全部换掉了,每个容器的ip是不一样的,为了保证容器之间能够互相通信,还需要提前创建一个网络,然后把ip换成这个网络的ip,每个容器递增就行,网关0.1,别的0.2,0.3递增就行。

网络相关指令如下:

创建完成之后,查看具体的ip,如果需要更多指令,通过help指令获取更多信息即可。通过下面的指令创建的是桥接(bridge)的网络。如果想要在创建容器的时候指定ip,需要在创建网络的时候就把子网掩码和网关全部定义好。如果不知道怎么定义合适,可以先创建一个网络,然后查看具体信息,再删除这个网络,利用刚刚查看的信息重新创建一个指定子网和网关的网络,这个子网和网关就是刚才删除的网络。

# 创建网络-指定子网和网关
docker network create --driver bridge --subnet ip/24 --gateway ip name
# 创建普通网络
docker network create name
# 查看网络信息
docker network inspect name
# 其他指令
docker network --help

2.2.3、启动容器

同样通过docker compose up -d启动,这里为了方便查看,推荐是先前台启动,再新开一个页面,手动下线主节点,观察是否能成功切换。确认能成功切换后再-d启动。

3、效果展示

[root@lavm-1c49qqovsf new]# docker compose up
[+] Running 6/6
 ? Container redis-master      Created 0.1s 
 ? Container redis-slave-1     Created 0.1s 
 ? Container redis-slave-2     Created 0.1s 
 ? Container redis-sentinel-3  Created 0.1s 
 ? Container redis-sentinel-1  Created 0.1s 
 ? Container redis-sentinel-2  Created 0.1s 
Attaching to redis-master, redis-sentinel-1, 
redis-sentinel-2, redis-sentinel-3, redis-slave-1, redis-slave-2

redis-master     * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-master     * Ready to accept connections tcp

redis-slave-2    * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-slave-2    * Ready to accept connections tcp

redis-slave-1    * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-slave-1    * Ready to accept connections tcp

redis-sentinel-1 # +monitor master redis-master masterip 6381quorum 2
redis-sentinel-2 # +monitor master redis-master masterip 6381quorum 2
redis-sentinel-3 # +monitor master redis-master masterip 6381quorum 2

redis-master     * Connecting to MASTER masterip:6381
redis-master     * MASTER <-> REPLICA sync started

redis-slave-1    * Connecting to MASTERmasterip:6381
redis-slave-1    * MASTER <-> REPLICA sync started

可以看到启动了6个容器,同时slave2是主节点,master和slave1是从节点,三个哨兵节点也是一致的认为slave2是主节点。

下面将slave进行下线处理,下线操作比较暴力,选择的是docker stop停止容器运行。

[root@lavm-1c49qqovsf ~]# docker stop redis-slave-2
redis-slave-2

redis-slave-2 exited with code 0

三个主观下线,以及哨兵沟通后一致认为6381客观下线

redis-sentinel-2   # +sdown master redis-master ip 6381
redis-sentinel-3   # +sdown master redis-master ip 6381
redis-sentinel-1   # +sdown master redis-master ip 6381

哨兵选举流程

下线原主节点

在经历了主观下线6381之后,三个哨兵开始投票,最终全部认为6381睡觉去了,然后开始选举新的主节点

redis-sentinel-3   # +try-failover master redis-master ip 6381
redis-sentinel-3   # +new-epoch 2
redis-sentinel-3   # +try-failover master redis-master ip port
redis-sentinel-3   # +vote-for-leader e9a22d6abb194fc462b8374053adb497b1151949 2
redis-sentinel-2   # +new-epoch 2
redis-sentinel-1   # +new-epoch 2
redis-sentinel-1   # +vote-for-leader e9a22d6abb194fc462b8374053adb497b1151949 2
redis-sentinel-2   # +vote-for-leader e9a22d6abb194fc462b8374053adb497b1151949 2
redis-sentinel-3   * 1895ade9cf2dec23e64215e61353e0c69cfaa89d voted for e9a22d6abb194fc462b8374053adb497b1151949 2
redis-sentinel-3   * b4ad213f757897f5d7977cdf46ee392a5a800bf9 voted for e9a22d6abb194fc462b8374053adb497b1151949 2
redis-sentinel-2   # +odown master redis-master ip 6381 #quorum 3/2
redis-sentinel-1   # +odown master redis-master ip 6381 #quorum 3/2
redis-sentinel-3   # +odown master redis-master ip 6381 #quorum 2/2

选举新主节点,选举过程稍后再说,最终结果是6380当选新的主节点,现在再上线6381

redis-sentinel-3   # +switch-master redis-master ip 6381 ip 6380
redis-sentinel-3   * +slave slave ip:6379 ip 6379 @ redis-master ip 6380
redis-sentinel-3   * +slave slave ip:6381 ip 6381 @ redis-master ip 6380

edis-sentinel-1    # +switch-master redis-master ip 6381 ip 6380
redis-sentinel-1   * +slave slave ip:6379 ip9 6379 @ redis-master ip 6380
redis-sentinel-1   * +slave slave ip:6381 ip 6381 @ redis-master ip 6380

redis-sentinel-2   # +switch-master redis-master ip 6381 ip 6380
redis-sentinel-2   * +slave slave ip:6379 ip 6379 @ redis-master ip 6380
redis-sentinel-2   * +slave slave ip:6381 ip 6381 @ redis-master ip 6380

重启slave2,重启之后会自动去连接当前的主节点并同步数据。

redis-slave-2    * Ready to accept connections tcp

redis-sentinel-2 # -sdown slave ip:6381 ip 6381 @ redis-master ip 6380
redis-sentinel-1 # -sdown slave ip:6381 ip 6381 @ redis-master ip 6380
redis-sentinel-3 # -sdown slave ip:6381 ip 6381 @ redis-master ip 6380
redis-sentinel-2 * +convert-to-slave slave ip:6381 ip 6381 @ redis-master ip 6380

redis-slave-2    * Connecting to MASTER ip:6380
redis-slave-2    * MASTER <-> REPLICA sync started
redis-slave-2    * Background AOF rewrite finished successfully

进入到redis容器内,查看节点状态,通过上面的操作,我们实现了,将主节点从6381切换到6380。下面验证6380是否是主节点以及另外两个节点是否是从节点。

使用到的指有

# 三个容器
docker exec -it  redis-master/slave-1/slave-2 bash

# 进入到容器后
redis-cli -a yourpassword -p port

# 进入到redis后
info replication

结果如下:

6379:

6380:

6381:

可以看到,79和81均为 slave节点,80为master节点。

自此,哨兵集群就实现了。

很烦,ip不打码或者改掉的话,会被扫描出漏洞,会被阿sir传唤整改。


评论