Redis第四话 -- redis高性能原理(多路复用)和高可用分析(备份、主从)

Redis一个作为一个缓存中间件,它的特点就是高性能。
那么性能能达到多高呢? 在官网中有明确测试代码,正常4核的机器是能达到QPS10W的。

1. Redis高性能原理

在前面的文章知道了Redis是纯内存访问的。
那么影响高性能的因素:

  • 内存
  • CPU
  • 网络IO

1.1 物理寻址

在前面的线程知识中,我们可以得知CPU运行速度是磁盘的N倍,那么再操作磁盘IO的时候就会导致CPU资源浪费,这也就有了上下文切换的概念。

在多核CPU中的,为什么可以同时运行成百上千的任务呢?
这取决于对进程的挂起和恢复,这个过程也就说我们常说的上下文切换。

比如liunx都是基于文件的,所以系统内核为了高效管理已经被打开的文件所创建的索引,用于指向被打开的文件,这个中索引就被称作文件描述符。在挂起和恢复的过程就是通过这个文件描述符去进行物理寻址的过程。

为什么会有上下文切换?
在一些进程执行系统服务请求但因为某种原因不能即时得到响应,则会将自己变成阻塞状态,释放CPU资源。

1.2 传统I/O拷贝数据

在这里插入图片描述
以上就是同步阻塞IO,如果在准备数据过程中会阻塞等待从而导致CPU资源浪费。

1.3 多路复用IO

同时支持多个Tcp连接(Socket或者channel),可以复用一个处理线程。
在这里插入图片描述
多路复用在Netty,NIO(Channel Buffer Selector,线程轮询 -> 监听收到消息后唤醒处理线程)中均有提现

1.4 多路复用之Reactor模型

  • 单线程Reactor模型
    在这里插入图片描述
    由Reactor直接分发到各个handler去,如果某个handler存在阻塞,整个分发也会阻塞
  • 多线程Reactor模型
    在这里插入图片描述
    Main Reactor -> Acceptor -> SubReactor(数组 读写分发) -> Handler
    由Reactor将请求直接丢到线程池,再由线程去分发到handler,不会存在阻塞问题,处理效率大大提升。

1.5 redis中的网络模型

  • 6.0版本之前是单线程Reactor模型,一个线程负责连接到读取到返回。
    在这里插入图片描述
    优点:不存在锁的问题,避免线程CPU上下文切换
    缺点:CPU无法被全利用到,串行操作太长的可能会阻塞后续操作

  • 6.0后采用多线程Reactor模型,读取由多个IO线程执行,只有执行操作是由主线程执行,这样可以解决线程安全问题,属于特殊的多线程Reactor模型
    在这里插入图片描述
    Threaded IO redis网络IO线程的数量,默认4个,默认关闭。在redis.conf中设置,最大线程8个。

高性能的原理搞懂了,接下来分析分析Redis中的内存回收策略。

2. Redis内存回收

2.1 回收方式

1.立即过期
需要不断的扫描所有带有过期时间的key,非常浪费资源

2.惰性过期
在获取时校验,缺点是不访问的话会一直占着内存

3.定期过期
有个线程会一直扫描存储了过期时间的key,取指定个数的随机值再决定是否全扫描

从字面意思看,惰性过期和定期过期配合使用最好

2.2 内存淘汰策略

Redis中64位的机器默认没有内存限制,超过内存会触发内存淘汰策略,在redis.conf中搜索memory查询到。命令下config get xxx 可以获取redis配置

当内存达到上限的时候,可以设置回收策略来释放部分无效的key,默认是noeviction返回报错。

  • volatile-lru, 针对设置了过期时间的key,进行LRU算法淘汰
  • all-lru, 针对所有的key,进行LRU算法淘汰
  • volatile-lfu, 针对设置了过期时间的key,进行LFU算法淘汰
  • all-lfu, 针对所有的key,进行LFU算法淘汰
  • volatile-random, 针对设置了过期时间的key,进行random淘汰
  • all-random, 针对所有的key,进行random淘汰
  • volatile-ttl, 删除生存时间最近的一个key
  • noeviction, 不删除key, 直接返回错误

2.3 回收算法 - LRU

Less Recently Used 最少使用
结构:HashMap(Key + Node) + Node 双向链表

在Redis 3.0中随机采用5个Key,放在链表中,然后随着链表的滚动淘汰末尾的Key。

3.0以后维护了大小为16的数组(空闲池),按Key的空闲时间排序(每个key维护了一个最后使用的时间),当插入随机采集的key时,有以下几种情况:
回收池满了的情况下:

  • 当插入的key空闲时间是最小的时候不做任何操作
  • 当插入的key是中间位置,则插入到指定位置,淘汰空闲时间最大的节点
    回收池没满的情况:
  • 插入最小的则追加到尾部节点
  • 插入最大的到指定位置,后续位置往后挪动

2.4 回收算法 - LFU

Least Frequently Used 最少访问次数,核心思想是淘汰过访问一次的数据
结构: HashMap + Node(横向和纵向的双向链表),横向表示访问次数,纵向存储通样频率的key。

Redis key中维护了一个count访问次数,用来做LFU算法。

一个存储中间件怎么能没有持久化呢?接下来分析分析持久化机制

3. Redis 持久化机制

数据备份,数据灾难恢复是可持续化的标准。是数据可靠性的保证。下面内容基于redis7.0实现

3.1 RDB快照(默认的持久化机制)

将内存中的数据刷入磁盘中的.rdb文件,触发条件:

  • redis.conf 中搜索save
#不配置刷盘时机,默认使用下面配置
#Unless specified otherwise, by default Redis will save the DB:
#一小时后至少有一个值被更新
#* After 3600 seconds (an hour) if at least 1 change was performed
#5分钟后至少有100个值被更新
#* After 300 seconds (5 minutes) if at least 100 changes were performed
#1分钟后只有有1W个值被更新
#* After 60 seconds if at least 10000 changes were performed
#
#You can set these explicitly by uncommenting the following line.

#save 3600 1 300 100 60 10000
  • shutdown停机
  • fushall会清空rdb文件
  • SAVE/BGSAVE命令,但两者之间各有差别
    • save命令执行时,客户端会阻塞,数据不会丢失
    • bgsave后台异步子线程处理,存在都是间隔时间内的数据
  • Master-Replica 主从复制时

优点:内容紧凑,适合数据定期备份,灾难恢复。fork()任务执行
缺点:不能实时持久化,可能丢失部分数据

3.2 RDB数据恢复

  • 通过docker启动redis
version: '3.7'
services:
  redis01:
    image: redis:7.0.0
    container_name: redis01
    ports:
    - "6379:6379"
    environment:
    - TZ=Asia/Shanghai
    volumes:
    - /root/local/redis/data:/data
    - /root/local/redis/redis.conf:/etc/redis/redis.conf
    networks:
    - my-net
    command: redis-server /etc/redis/redis.conf
networks:
  #新增的网络 内部服务名调用
  my-net:
    external: true
  • 进入容器内部测试RDB文件生成
root@5fb8e741be10:/data# redis-cli 
127.0.0.1:6379> set k1 123
OK
127.0.0.1:6379> set k2 123
OK
#手动生成rdb文件
127.0.0.1:6379> save
OK
127.0.0.1:6379> set k3 123
OK
#在这里备份rdb文件
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> shutdown
[root@m redis]# docker-compose up -d
Starting redis01 ... done
[root@m redis]# docker exec -it redis01 /bin/bash
root@5fb8e741be10:/data# redis-cli 
#再次重启 可以看到DB是空的
127.0.0.1:6379> keys *
(empty array)
#再次停掉,进行数据恢复
127.0.0.1:6379> shutdown
[root@m redis]# rm -fr data/dump.rdb 
#将备份的rdb文件覆盖回去
[root@m redis]# mv data/dump1.rdb data/dump.rdb
[root@m redis]# docker-compose up -d
Starting redis01 ... done
[root@m redis]# docker exec -it redis01 /bin/bash
root@5fb8e741be10:/data# redis-cli 
#数据恢复到上一次刷盘
127.0.0.1:6379> keys *
1) "k1"
2) "k2"

缺点也很明显,不能实时持久化,可能会丢失数据

3.3 AOF持久化机制

以执行指令日志的形式记录,默认是关闭。可通过redis.conf中搜索appendonly开启,开启成功会生成appendonly.aof文件。

#默认关闭
appendonly no
#生成的文件名
appendfilename "appendonly.aof"
#刷盘时机 每次
# appendfsync always
#默认的刷盘时机 每秒
appendfsync everysec
#关闭 不自动刷盘
# appendfsync no
  • 进入容器内执行
root@b9fc72ba0b05:/data# redis-cli 
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set k1 1234
OK
127.0.0.1:6379> shutdowm
[root@m redis]# ls data/
#停机也会触发dump.rdb
appendonlydir  dump.rdb
[root@m redis]# ls data/appendonlydir/
appendonly.aof.1.base.rdb  appendonly.aof.1.incr.aof  appendonly.aof.manifest
#记录的正是执行的指令
[root@m redis]# cat data/appendonlydir/appendonly.aof.1.incr.aof 
*2
$6
SELECT
$1
0
*3
$3
set
$2
k1
$4
1234

AOF文件是能直接查看到执行指令的,那存储执行指令肯定会非常占用磁盘资源,那在什么时候做合并呢?redis中有rewrite配置:

#当前aof文件超过上次重写文件的百分之多少的时候会触发
auto-aof-rewrite-percentage 100
#大于64M
auto-aof-rewrite-min-size 64mb

当子进程在执行AOF文件重写是,主进程需要执行三个操作

  • 处理客户端请求
  • 将命令追加到现有的AOF文件中
  • 将写命令追到到重写缓存中

两者都开启的情况,可以使用dump备份数据,使用aof恢复数据。
持久化机制分析完了,那怎么能少得了分布式高可用呢?

4.Redis高可用

高可用有哪些实现:主从(Master - Slave)、主主(Master - Master,只有一个节点在工作,相当于备用机)、RedisClustre(数据分布,不同节点不同数据)

4.1 Redis的高可用机制

一主多从:Master Slave从节点向主节点请求数据,缺点:没有解决高可用,需要手动切换主从
哨兵机制:Leader follwer,单独的进程,会连接到所有的节点,当Master挂了,会从slave节点中重新选举出Master。客户端是直接连到哨兵节点的地址,有哨兵提供真实的Redis Master地址
哨兵配置,redis自带的sentinel.conf

4.2 一主多从实现

虚拟机liunx centos7 一台,6379为master,16379为slave。docker-compose文件如下。

version: '3.7'
services:
  redis-master:
    image: redis:7.0.0
    container_name: redis-master
    ports:
    - "6379:6379"
    environment:
    - TZ=Asia/Shanghai
    volumes:
    - /root/local/redis/data:/data
    networks:
    - my-net
    command: redis-server
  redis-slave:
    image: redis:7.0.0
    container_name: redis-slave
    ports:
    - "16379:6379"
    environment:
    - TZ=Asia/Shanghai
    volumes:
    - /root/local/redis/data:/data
    networks:
    - my-net
    #相当于进入容器执行了 slaveof host port 指令
    command: redis-server --slaveof redis-master 6379
networks:
  #新增的网络 内部服务名调用
  my-net:
    external: true
  • 接下来进入容器查看信息
root@ffedc4633580:/data# redis-cli 
127.0.0.1:6379> info replication
# Replication 权限标识为slave
role:slave
#master机器的host和端口
master_host:redis-master
master_port:6379
master_link_status:up
master_last_io_seconds_ago:4
master_sync_in_progress:0
slave_read_repl_offset:864
#从机当前数据的下标 和master机的下标相等说明同步到最新
slave_repl_offset:864
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:e767f471af578226d154fa7a4504940ab777c261
master_replid2:fdd6c3eaa377ad5bb8d3542f53209a382dbfeaca
#master机当前数据的下标
master_repl_offset:864
second_repl_offset:823
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:823
repl_backlog_histlen:42
#从节点不支持写入
127.0.0.1:6379> set k1 1234
(error) READONLY You can't write against a read only replica.
#master节点写入数据后 从节点可以正常查询到
127.0.0.1:6379> get k123
"134"
#执行此命令则表示脱离从节点,自己变为master
127.0.0.1:6379> slaveof no one
OK
(9.68s)
127.0.0.1:6379> info replication
# Replication 权限已经改变
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:5d8ea4f09e183d5c8f11750e1947114fef542b1a
master_replid2:e767f471af578226d154fa7a4504940ab777c261
master_repl_offset:1395
second_repl_offset:1396
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:823
repl_backlog_histlen:573
#可以正常写入
127.0.0.1:6379> set k3 13
OK

额外补充
如果用的是redis.conf,可以在这里设置

#跟随master Ip和端口
# replicaof <masterip> <masterport>

在命令行info replication查看节点信息,这种基本上已经不用了,因为不能主从切换!
redis中还基于这个主从提供了一种可以切换主从的哨兵机制。

4.3 主从哨兵实现

基于上面的主从新添加了一套监控的存在,简称哨兵。可以在主从之间实现节点切换!

  • 一主二从docker-compose.yaml文件如下:
version: '3.7'
services:
  redis-master:
    image: redis:7.0.0
    container_name: redis-master
    ports:
    - "6379:6379"
    environment:
    - TZ=Asia/Shanghai
    networks:
    - my-net
    #如果有其他配置项 可根据带上文件启动
    command: redis-server 
  redis-slave1:
    image: redis:7.0.0
    container_name: redis-slave1
    ports:
    - "6378:6379"
    environment:
    - TZ=Asia/Shanghai
    networks:
    - my-net
    #不走配置文件replicaof xx xx,直接走命令参数
    command: redis-server --slaveof redis-master 6379
  redis-slave2:
    image: redis:7.0.0
    container_name: redis-slave2
    ports:
    - "6377:6379"
    environment:
    - TZ=Asia/Shanghai
    networks:
    - my-net
	#不走配置文件replicaof xx xx,直接走命令参数
    command: redis-server --slaveof redis-master 6379

networks:
  #新增的网络 内部服务名调用
  my-net:
    external: true
  • sentinel哨兵配置如下,sentinel.conf
port 26379
#如果需要外网访问哨兵从而得到真实的master节点地址 需要加上这行 不然连接的会是内网ip
bind 0.0.0.0
dir /tmp
# 自定义集群名,其中 192.168.0.221 为 redis-master 的 ip,6379 为 redis-master 的端口,2 为最小投票数(因为有 3 台 Sentinel 所以可以设置成 2)
sentinel monitor mymaster 192.168.0.221 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
#sentinel auth-pass mymaster test@dbuser2018
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
  • 将sentinel.conf复制成三份,sentinel docker-compose.yaml如下
version: '3.7'
services:
  redis-sentinel1:
    image: redis:7.0.0
    container_name: redis-sentinel1
    ports:
    - "26379:26379"
    environment:
    - TZ=Asia/Shanghai
    volumes:
    - /root/local/redis-sentinel/sentinel/sentinel1.conf:/etc/redis/sentinel.conf
    networks:
    - my-net
    #指定配置启动
    command: redis-sentinel /etc/redis/sentinel.conf
  redis-sentinel2:
    image: redis:7.0.0
    container_name: redis-sentinel2
    ports:
    - "26378:26379"
    environment:
    - TZ=Asia/Shanghai
    volumes:
    - /root/local/redis-sentinel/sentinel/sentinel2.conf:/etc/redis/sentinel.conf
    networks:
    - my-net
    #指定配置启动
    command: redis-sentinel /etc/redis/sentinel.conf
  redis-sentinel3:
    image: redis:7.0.0
    container_name: redis-sentinel3
    ports:
    - "26377:26379"
    environment:
    - TZ=Asia/Shanghai
    volumes:
    - /root/local/redis-sentinel/sentinel/sentinel3.conf:/etc/redis/sentinel.conf
    networks:
    - my-net
    #指定配置启动
    command: redis-sentinel /etc/redis/sentinel.conf

networks:
  #新增的网络 内部服务名调用
  my-net:
    external: true
  • 启动容器,并查看
[root@m sentinel]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                NAMES
0cf98dd91728        redis:7.0.0         "docker-entrypoint.s…"   11 minutes ago      Up 11 minutes       6379/tcp, 0.0.0.0:26377->26379/tcp   redis-sentinel3
c2f4f8a21c89        redis:7.0.0         "docker-entrypoint.s…"   11 minutes ago      Up 11 minutes       6379/tcp, 0.0.0.0:26379->26379/tcp   redis-sentinel1
e924c05cc52c        redis:7.0.0         "docker-entrypoint.s…"   11 minutes ago      Up 11 minutes       6379/tcp, 0.0.0.0:26378->26379/tcp   redis-sentinel2
78fd96a432b6        redis:7.0.0         "docker-entrypoint.s…"   18 hours ago        Up 14 minutes       0.0.0.0:6378->6379/tcp               redis-slave1
f376e2906928        redis:7.0.0         "docker-entrypoint.s…"   18 hours ago        Up 14 minutes       0.0.0.0:6377->6379/tcp               redis-slave2
036619381f67        redis:7.0.0         "docker-entrypoint.s…"   18 hours ago        Up 49 seconds       0.0.0.0:6379->6379/tcp               redis-master

均启动成功即可,如未启动成功的,可到对应docker-compose目录下使用docker-compose logs查看日志。特别注意一点:在复制之前一定要保证不要有隐藏的编码问题,否则根本启动不了,也没日志!

  • redis从机测试
[root@m sentinel]# docker exec -it redis-slave2 /bin/bash
root@f376e2906928:/data# redis-cli 
127.0.0.1:6379> info replication
# Replication 主从没问题
role:slave
master_host:172.19.0.3
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:195767
slave_repl_offset:195767
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:992b891eb5873ed5034e363876f5914b69708eea
master_replid2:77aa1f4d53eacdcbf529b46229087c55e8b51065
master_repl_offset:195767
second_repl_offset:61316
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:14812
repl_backlog_histlen:180956
  • 哨兵是否正常测试,进入任意一台哨兵
[root@m sentinel]# docker exec -it redis-sentinel2 /bin/bash
root@e924c05cc52c:/data# redis-cli -p 26379
127.0.0.1:26379> sentinel master mymaster
 1) "name"
 2) "mymaster"
 3) "ip"
 4) "172.19.0.3"
 5) "port"
 6) "6379"
 7) "runid"
 8) "40a0a02da2b95482650f9f9ebdb9fde1bd7c7aff"
 9) "flags"
10) "master"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "920"
19) "last-ping-reply"
20) "920"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "7352"
25) "role-reported"
26) "master"
27) "role-reported-time"
28) "801790"
29) "config-epoch"
30) "1"
31) "num-slaves"
32) "4"
33) "num-other-sentinels"
34) "2"
35) "quorum"
36) "2"
37) "failover-timeout"
38) "180000"
39) "parallel-syncs"
40) "1"

如出现上述内容视为正常。

  • 主从切换测试
[root@m sentinel]# docker stop redis-master
redis-master
#进入第一台从机
[root@m redis-sentinel]# docker exec -it redis-slave1 /bin/bash
root@78fd96a432b6:/data# redis-cli
127.0.0.1:6379> info replication
# Replication 此时的角色还是slave
role:slave
master_host:192.168.0.221
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_read_repl_offset:61315
slave_repl_offset:61315
master_link_down_since_seconds:8
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:77aa1f4d53eacdcbf529b46229087c55e8b51065
master_replid2:3ce84a32c2c3df233316240b3e5d4f7df4a31349
master_repl_offset:61315
second_repl_offset:14812
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:14812
repl_backlog_histlen:46504
127.0.0.1:6379> info replication
# Replication 在等待几秒后再次查看已经发现变更为master了
role:master
connected_slaves:1 #从节点变更为1了
slave0:ip=172.19.0.4,port=6379,state=online,offset=67045,lag=1
master_failover_state:no-failover
master_replid:992b891eb5873ed5034e363876f5914b69708eea
master_replid2:77aa1f4d53eacdcbf529b46229087c55e8b51065
master_repl_offset:67180
second_repl_offset:61316
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:14812
repl_backlog_histlen:52369
  • 查看sentinel日志
[root@m sentinel]# docker-compose logs
#在里面找到关键的信息
# master节点已经断开了
redis-sentinel2    | 1:X 09 Jun 2022 15:26:30.215 # +failover-end master mymaster 192.168.0.221 6379
#推举ip 0.3为master
redis-sentinel2    | 1:X 09 Jun 2022 15:26:30.215 # +switch-master mymaster 192.168.0.221 6379 172.19.0.3 6379
#0.1变为slave 即以前的master
redis-sentinel2    | 1:X 09 Jun 2022 15:26:30.216 * +slave slave 172.19.0.1:6379 172.19.0.1 6379 @ mymaster 172.19.0.3 6379
#0.4跟着变更
redis-sentinel2    | 1:X 09 Jun 2022 15:26:30.216 * +slave slave 172.19.0.4:6379 172.19.0.4 6379 @ mymaster 172.19.0.3 6379
redis-sentinel2    | 1:X 09 Jun 2022 15:26:30.216 * +slave slave 192.168.0.221:6379 192.168.0.221 6379 @ mymaster 172.19.0.3 6379

4.4 哨兵原理图

在这里插入图片描述

4.5 哨兵机制总结

如何判断节点断开:
心跳包超时,根据配置了几个哨兵发现超时来决定

如果决定哪个成为master:

  • 配置文件中的优先级
  • 同步文件的数量大小
  • 超时时间
  • 同步文件中的offset下标

如何决定谁成为sentinel leader
Raft协议少数服从多数,每个机器都把自己投票的票据发送给其他机器,哪张被半数机器同意则成为leader,(发送时间会等待随机时间,避免每次每台机器都在同一时间发送)

4.6 Raft 一致性算法

少数服从多数,投票票数必须大于半数,可以实现集群选主的功能。这也是为什么集群需要是奇数个
Leader-follower启动时都是follower,由Raft协议从中选出leader
集群选主实现一般出现在启动和节点挂了的情况

每一轮发送推举自己的票据给其他节点,在时间(150ms-300ms)周期内发送一次,最终能哪个节点的票据统一则成为leader

成为leader后同步,采用的是二阶段提交,达到最终一致。
例如在选举过程中有数据写入,那么需要至少过半机器成功才会返回客户端成功,这个过程叫做过半确认(2pc)

5 Redis Cluster集群

redis中还有一种多主多从的集群,即Redis Cluster。集群必须要求:三主三从
基于redis7.0实现,端口6374-6379,6377-6379为master节点

5.1 配置文件redis.conf

#集群端口
port ${PORT}
#开启集群
cluster-enabled yes
#集群名
cluster-config-file nodes.conf
cluster-node-timeout 5000
#集群Ip需要写宿主机IP
cluster-announce-ip 192.168.0.221
#开启持久化
appendonly yes

5.2 创建目录

也可手动创建,目录结构./6379/conf/redis.conf ./6379/data

for port in `seq 6374 6379`;do mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis.conf> ./${port}/conf/redis.conf && mkdir -p ./${port}/data; done

这里用到的端口是6374-6379,如果不同机器可用overlay网络+docker swarm,达到服务别名访问

5.3 docker run命令启动

for port in `seq 6374 6379`;do docker run -d --name redis-${port} -v `pwd`/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf -v `pwd`/${port}/data:/data -p ${port}:${port} -p 1${port}:1${port} redis:7.0.0 redis-server /usr/local/etc/redis/redis.conf ; done

也可以用docker-compose,方便管理

5.4 docker-compse文件启动

用一个网络下可以用别名访问,但是如果跨宿主机需要用到overlay+docker swarm

version: '3'
services:
  master1:
    image: "redis:7.0.7"
    container_name: redis-m1
    ports:
    - "6379:6379"
    - "16379:16379"
    networks:
    - my-net
    volumes:
    - ./6379/data:/data
    - ./6379/conf/redis.conf:/usr/local/etc/redis/redis.conf
    command: redis-server /usr/local/etc/redis/redis.conf
    
networks:
  #表示使用已创建的网络
  my-net:
    external: true

其他的自己复制,需要注意端口和容器名称。

5.5 加入集群

  • ip需要填写宿主机ip,一种直接通过客户端连接直接加入集群的命令
docker run -it --rm goodsmileduck/redis-cli:latest redis-cli --cluster-replicas 1 --cluster create 192.168.0.221:6379 192.168.0.221:6378 192.168.0.221:6377 192.168.0.221:6376 192.168.0.221:6375 192.168.0.221:6374
  • 也可以进入任意一个容器内部执行加入集群的命令
docker exec -it redis-m1 /bin/bash;
redis-cli --cluster-replicas 1 --cluster create 192.168.0.221:6379 192.168.0.221:6378 192.168.0.221:6377 192.168.0.221:6376 192.168.0.221:6375 192.168.0.221:6374

至此,三主三从的搭建到此完毕。

Redis的整个内容至此就结束了,真怀念学习时候的状态!
以上就是本章的全部内容了。

上一篇:Redis第三话 – Springboot集成Redis以及常用API和客户端介绍)
下一篇:Zookeeper第一话 – docker安装zookeeper以及Springboot集成zk

书山有路勤为径,学海无涯苦作舟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值