Redis一个作为一个缓存中间件,它的特点就是高性能。
那么性能能达到多高呢? 在官网中有明确测试代码,正常4核的机器是能达到QPS10W的。
在前面的文章知道了Redis是纯内存访问的。
那么影响高性能的因素:
- 内存
- CPU
- 网络IO
在前面的线程知识中,我们可以得知CPU运行速度是磁盘的N倍,那么再操作磁盘IO的时候就会导致CPU资源浪费,这也就有了上下文切换的概念。
在多核CPU中的,为什么可以同时运行成百上千的任务呢?
这取决于对进程的挂起和恢复,这个过程也就说我们常说的上下文切换。
比如liunx都是基于文件的,所以系统内核为了高效管理已经被打开的文件所创建的索引,用于指向被打开的文件,这个中索引就被称作文件描述符。在挂起和恢复的过程就是通过这个文件描述符去进行物理寻址的过程。
为什么会有上下文切换?
在一些进程执行系统服务请求但因为某种原因不能即时得到响应,则会将自己变成阻塞状态,释放CPU资源。
以上就是同步阻塞IO,如果在准备数据过程中会阻塞等待从而导致CPU资源浪费。
同时支持多个Tcp连接(Socket或者channel),可以复用一个处理线程。
多路复用在Netty,NIO(Channel Buffer Selector,线程轮询 -> 监听收到消息后唤醒处理线程)中均有提现
- 单线程Reactor模型
由Reactor直接分发到各个handler去,如果某个handler存在阻塞,整个分发也会阻塞 - 多线程Reactor模型
Main Reactor -> Acceptor -> SubReactor(数组 读写分发) -> Handler
由Reactor将请求直接丢到线程池,再由线程去分发到handler,不会存在阻塞问题,处理效率大大提升。
-
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, 直接返回错误
Less Recently Used 最少使用
结构:HashMap(Key + Node) + Node 双向链表
在Redis 3.0中随机采用5个Key,放在链表中,然后随着链表的滚动淘汰末尾的Key。
3.0以后维护了大小为16的数组(空闲池),按Key的空闲时间排序(每个key维护了一个最后使用的时间),当插入随机采集的key时,有以下几种情况:
回收池满了的情况下:
- 当插入的key空闲时间是最小的时候不做任何操作
- 当插入的key是中间位置,则插入到指定位置,淘汰空闲时间最大的节点
回收池没满的情况: - 插入最小的则追加到尾部节点
- 插入最大的到指定位置,后续位置往后挪动
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()任务执行
缺点:不能实时持久化,可能丢失部分数据
- 通过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恢复数据。
持久化机制分析完了,那怎么能少得了分布式高可用呢?
高可用有哪些实现:主从(Master - Slave)、主主(Master - Master,只有一个节点在工作,相当于备用机)、RedisClustre(数据分布,不同节点不同数据)
4.1 Redis的高可用机制一主多从:Master Slave从节点向主节点请求数据,缺点:没有解决高可用,需要手动切换主从
哨兵机制:Leader follwer,单独的进程,会连接到所有的节点,当Master挂了,会从slave节点中重新选举出Master。客户端是直接连到哨兵节点的地址,有哨兵提供真实的Redis Master地址
哨兵配置,redis自带的sentinel.conf
虚拟机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
在命令行info replication查看节点信息,这种基本上已经不用了,因为不能主从切换!
redis中还基于这个主从提供了一种可以切换主从的哨兵机制。
基于上面的主从新添加了一套监控的存在,简称哨兵。可以在主从之间实现节点切换!
- 一主二从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 63794.4 哨兵原理图 4.5 哨兵机制总结
如何判断节点断开:
心跳包超时,根据配置了几个哨兵发现超时来决定
如果决定哪个成为master:
- 配置文件中的优先级
- 同步文件的数量大小
- 超时时间
- 同步文件中的offset下标
如何决定谁成为sentinel leader
Raft协议少数服从多数,每个机器都把自己投票的票据发送给其他机器,哪张被半数机器同意则成为leader,(发送时间会等待随机时间,避免每次每台机器都在同一时间发送)
少数服从多数,投票票数必须大于半数,可以实现集群选主的功能。这也是为什么集群需要是奇数个。
Leader-follower启动时都是follower,由Raft协议从中选出leader
集群选主实现一般出现在启动和节点挂了的情况
每一轮发送推举自己的票据给其他节点,在时间(150ms-300ms)周期内发送一次,最终能哪个节点的票据统一则成为leader
成为leader后同步,采用的是二阶段提交,达到最终一致。
例如在选举过程中有数据写入,那么需要至少过半机器成功才会返回客户端成功,这个过程叫做过半确认(2pc)
redis中还有一种多主多从的集群,即Redis Cluster。集群必须要求:三主三从
基于redis7.0实现,端口6374-6379,6377-6379为master节点
#集群端口
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
书山有路勤为径,学海无涯苦作舟



