主从和集群 区别
基本说明 和 存储不同
主从:一主多从
- 主节点和从节点都是存储所有数据;
集群:多主多从
- 数据的存储是通过hash计算16384的槽位,算出要将数据存储的节点,然后进行存储;
主节点挂了 选举不同
主从:通过自带的哨兵(sentinel)
- 先发现主节点fail的哨兵,将成为哨兵中的leader
- 通过这个leader进行故障转移操作,从存活的slave中选举新的master
集群:可以自己进行选举
-
从节点就会广播该主节点fail;
-
延迟时间后进行选举,延迟的原因是等待主节点fail广播到 所有存活的主节点
-
参加选举的从节点向所有的存活的节点发送ack请求,但只有主节点会回复它,
- 并且主节点只会回复第一个到达参加选举的从节点,一半以上的主节点回复,该节点就会成为主节点,
-
广播告诉其他节点 该节点成为主节点。
节点扩容不同
- 主从:只能扩容从节点
- 集群:可以扩容 主 从 节点
Redis 集群中进行分片操作:
redis-cli -a 密码XX --cluster reshard 192.168.0.61:8001
解释:--cluster reshard 对集群的 该节点进行分片操作,哪个节点?就是 后面跟的 IP:端口
reshard v.重新切分
shard n.陶瓷碎片
此命令:将一个 Redis 节点上的一部分数据 迁移到集群中的其他节点上,以实现负载均衡或扩展 Redis 集群的容量。
Redis说明
数据类型
-
字符串 String
-
散列 Hash
-
列表 List
-
集合 Set
-
有序集合 Zset
-
SortedSet(有序集合类型,简称zset) 如:zadd myset 1 one 2 two 3 three
-
-
地理空间 geospatial
-
基数 hyperloglog
- 两个合并后,去掉重复的元素。
-
位图 bitmaps
- 数据结构。如:放置365天,每天的状态 是否打卡了。
QPS
- 官方提供的数据为100000+的QPS
关于版本
-
2023年12月21日,在官网 https://redis.io/download/
-
可以看到,最新的稳定版为 7.2.3
- 老版本 7.0.14 和 6.2.14
-
通过官方给的 Docker仓库 https://hub.docker.com/_/redis(需要外网)
-
可以看到:Docker稳定版常用
7.2.3 7.2 7.0.14 7.0 6.2.14 6.2 6.0.20
安装和使用
官方的配置
- 连接如下:
http://download.redis.io/redis-stable/redis.conf
常用的配置
#注释掉这部分,这是限制redis只能本地访问
bind 127.0.0.1
#默认yes,开启保护模式,限制为本地访问
protected-mode no
#默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败
daemonize no
#redis持久化(可选)
appendonly yes
#设置密码
requirepass 123456
Docker安装
最简单的启动 不推荐
docker search redis #查看下Docker仓库和Redis相关的
docker pull redis
docker run -p 6379:6379 -d redis:latest redis-server
docker run -p 6379:6379
-v $PWD/data:/data
-d redis:latest
redis-server --appendonly yes
复杂的参数 非常推荐
-
如在当前目录下新建 /redis723
-
修改配置文件 redis.conf
appendonly yes
requirepass 123456
注释:bind 127.0.0.1
-
进入 redis723,放入 redis.conf
-
执行下面命令,成功后,使用 密码 即可连接成功
docker run --name redis-test -p 6379:6379 -v $PWD/redis.conf:/etc/redis/redis.conf -v $PWD/data:/data -d redis:latest redis-server ../etc/redis/redis.conf --appendonly yes
参数说明
docker run
--name redis-test #起个名,正式环境 起名可以 redis01
-p 6379:6379 #将容器的6379端口映射到主机的6379端口
-v $PWD/redis.conf:/etc/redis/redis.conf #当前目录下的redis.conf,挂载到容器
-v $PWD/data:/data #当前目录下的/data挂载到data
-d redis:latest #后台运行,使用哪个版本
redis-server ../etc/redis/redis.conf --appendonly yes
#使用容器内的配置文件。打开redis持久化配置
#因为上面 已经修改了配置文件 --appendonly yes 加不加都一样
#如果你是win电脑,可以这样映射
-v D:/docker/redis/redis.conf:/etc/redis/redis.conf
-v D:/docker/redis/data:/data
-v $PWD/data:/data : 将主机中当前目录下的data挂载到容器的/data
:latest 可以改成你的版本 如 :7.2.3
#也可以使用直接路径。一样的。
redis-server /usr/local/etc/redis/redis.conf
本机安装
- 官方安装的路径:https://redis.io/docs/install/install-redis/install-redis-on-linux/
- 输入如下命令:
sudo apt install lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis
- 启动
/etc/init.d/redis-server start
systemctl start redis-server
redis-server redis6381.conf #启动其他的配置文件
service redis-server start
service redis-server restart
service redis-server stop
service redis-server status
/etc/redis/redis.conf
bind 127.0.0.1 -::1
requirepass 你的密码
protected-mode no #保护模式关闭,不关闭Java可能无法连接
安装在了:如下目录下
/usr/bin/
还要安装哨兵
apt install redis-sentinel
Java连接
- https://redis.io/docs/connect/clients/java/
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version>
</dependency>
@SpringBootTest
class RedisTests {
@Test
void contextLoads() {
JedisPool pool = new JedisPool("192.168.254.128", 6379);
try (Jedis jedis = pool.getResource()) {
jedis.set("foo", "bar");
System.out.println(jedis.get("foo"));
Map<String, String> hash = new HashMap<>();
hash.put("name", "John");
hash.put("surname", "Smith");
hash.put("company", "Redis");
hash.put("age", "29");
jedis.hset("user-session:123", hash);
System.out.println(jedis.hgetAll("user-session:123"));
}
}
//不需要try catch
JedisPooled jedis = new JedisPooled("localhost", 6379);
jedis.set("foo", "bar");
System.out.println(jedis.get("foo")); // prints "bar"
查看版本
- 如果你安装的是 latest,可能不知道 自己的版本
直连容器:
docker exec -it 你的启动的容器ID redis-cli -h localhost -p 6379 -a 123456
使用命令:
INFO SERVER
即可看到:
# Server
redis_version:7.2.3
或者先进入容器:
docker exec -it 你的启动的容器ID bash
#bash 和 /bin/bash 一样
使用命令:
redis-server --version
即可看到:
Redis server v=7.2.3
基本使用
#进入容器后
redis-cli -h localhost -p 6379 -a 123456
auth 123456 #单独用命令登录。上面 -a 已经登录过了
OK
set test 111
OK #显示OK,说明成功了
get test
"111"
keys *
select 3 #选择3数据库。
flushdb
flushall #清空所有库,压力测试放的数据,也会清空。
其他相关
RDB AOF介绍
Redis中的RDB(Redis DataBase)和AOF(Append Only File)是两种持久化方式。
RDB是一种快照持久化方式,它会在指定的时间间隔内生成数据的时间点快照,并将快照保存到磁盘上的文件中。这种方式的优点是生成的快照文件比较小,适合用于备份数据或者进行全量恢复。
AOF则是一种追加写日志的方式,它会将Redis服务器接收到的每一条写命令都追加到AOF文件的末尾。通过重放AOF文件中的写命令,可以在服务器重启时恢复数据。AOF的优点是在发生故障时,可以最大程度地保留数据,但相对来说AOF文件会比RDB文件大。
根据自己的需求选择使用RDB、AOF或者两者结合的方式来进行持久化
RDB执行步骤
- 父进程,fork 一个子进程
- 将内存内容写入 临时RDB文件
- 快照写入完成后,替换原来的快照文件
- 成为:正式 RDB 文件。
- 我们默认的就是RDB,一般情况下不需要修改这个配置!
- rdb保存的文件是dump.rdb
AOF执行步骤
- 父进程 fork 一个子进程
- 根据内存中数据快照。写入重建数据库状态的命令
- 临时AOF文件
- 父进程将缓存的与命令写入临时文件
- 父进程用临时文件替换旧的AOF文件井重命名。
RDB快照配置
-
持久化,在规定的时间内,执行了多少次操作,则会持久化到文件.rdb.aof
-
redis是内存数据库,如果没有持久化,那么数据断电及失!
#如果900秒内,如果至少有一个1 key进行了修改,我们就进行持久化操作
save 900 1
#save 60 5 #在60秒内,修改5个值,就保存
#如果300s内,如果至少10 key进行了修改,我们及进行持久化操作
save 300 10
#如果60s内,如果至少10000 key进行了修改,我们及进行持久化操作
save 60 10000
stop-writes-on-bgsave-error yes #持久化如果出错,是否还需要维续工作!
rdbcompression yes #是否压缩rdb文件,需要消耗一些cpu资源!
rdbchecksum yes #保存rdb文件的时候,进行错误的检查校验!
dbfilename dump.rdb
dir ./ #rdb文件保存的目录!
AOF配置
appendonly no #默认是不开启aof模式的,默认是使用rdb方式持久化的,在大都分所有的情况下,rdb完全够用!
appendfilename "appendonly.aof"
# appendfsync always #每次修改都会sync。消耗性能
appendfsync everysec #每秒执行一次 sync,可能会丢失这1s的数据!
# appendfsync no #不执行sync,这个时候操作系统自己同步数据,速度最快!
no-appendfsync-on-rewrite no
#如果当前 AOF 文件的增长量大于上次 AOF 文件的 100%,就会触发重写操作;
auto-aof-rewrite-percentage 100
#指定触发重写操作的 AOF 文件的大小,默认为 64MB。
auto-aof-rewrite-min-size 64mb
#同时满足以上这两个选项所设置的条件,才会触发重写操作
aof-use-rdb-preamble yes #混合存放
默认是不开启的,我们需要手动进行配置!我们只需要将appendonly改为yes就开启了aof !重启,redis 就可以生效了!
如果这个aof文件有错位,这时候redis是启动不起来的吗,我们需要修复这个aof文件redis给我们提供了一个工具redis-check-aof --fix
redis-check-aof --fix appendonly.aof
Redis 4.0 混合持久化
aof-use-rdb-preamble yes
- aof rewrite 的时候就直接把 rdb 的内容写到 aof 文件开头。
内存达上线处理策略
edis2.6+版本,redis.conf中的默认的策略是 noeviction ,一共有八种:
volatile-lru:只对设置了过期时间的key进行LRU算法进行删除
allkeys-lru : 对所有key执行LRU算法进行删除
volatile-lfu:只对设置了过期时间的key进行LFU算法进行删除
allkeys-lfu:对所有key执行LFU算法进行删除
volatile-random:随机删除设置有过期时间的key
allkeys-random:随机删除
volatile-ttl : 删除即将过期的
noeviction : 永不过期,返回错误
LFU(Least Frequently Used ) 最不经常使用的
LRU是Least Recently Used的缩写,即最近最少使用
订阅者 发布者
subscribe test01
#输入上面命令后出现
1) "subscribe"
2) "test01"
3) (integer) 1
publish test01 hello #另一个终端发布
(integer) 1
1) "message" #上面终端,会收到消息
2) "test01"
3) "hello"
缓存穿透 击穿
缓存穿透、缓存雪崩和缓存击穿
穿透(查不到)
- 比如 用户2,在缓冲中,和 数据里 都没有这个数据
- 客户 大量的查询这个数据。
- 解决:加一个过滤器。或 user2放入 一个缓存 为 空。
布隆过滤器
- 布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,
缓存空对象
击穿(热点 查的太多了)
一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
缓存60秒 过期,在 60.1s秒后,有个新的缓存。
- 0.1秒内,有非常多的 请求过来,查询数据库。
设置热点数据永不过期
加互斥锁
- 同一时间,只能有一个 线程去后台查询数据库。
- 加锁只保证只有一个线程进去其余的讲行等待
- 分布式锁:使用分布式锁
缓存雪崩
是指在某一个时间段,缓存集中过期失效。Redis宕机
redis高可用
停掉一些 非主流程,给 主流程让路。
限流降级
数据预热
主从复制
简介
主从复制,读写分离
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。
- 前者称为主节点(master/leader),后者称为从节点(slave/follower);
- 数据的复制是单向的,只能由主节点到从节点。
- Master以写为主,Slave以读为主。
作用
- 数据冗余
- 故障恢复
- 负载均衡
主节点提供写服务,由从节点提供读服务
(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),
分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
- 高可用基石
主从复制还是哨兵和集群能够实施的基础
info指令
info replication #只展示 和 主从复制相关的
# Replication
role:master #默认为 主节点
connected_slaves:0 #没有从机
info #展示所有相关的
# Server
redis_version:5.0.8
# Clients
connected_clients:1
# Memory
used_memory:854616
# Persistence
loading:0
# Stats
total_connections_received:5
# Replication 上面info replication就是这里的指令
role:master
connected_slaves:0
# CPU
used_cpu_sys:0.573733
# Cluster
cluster_enabled:0
一主二从
- 可以启动3个
prot 6379
pidfile /var/run/redis_6379.pid
logfile "6379.log"
dbfilename dump6379.rdb
命令配置从节点
#连接 80 和 81
redis-cli -p 6380
slaveof 127.0.0.1 6379
info replication #从节点 查看
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
info replication #主节点 查看
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=112,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=112,lag=1
配置文件配置从节点
# replicaof <masterip> <masterport>
replicaof xx xx
# masterauth <master-password> #主机有密码,也要配置
从机不能写
主机可以写,从机不能写只能读!主机中的所有信息和数据,都会自动被从机保存!
set k1 v1
(error) READONLY You can't write against a read only replica.
使用配置文件
- 主机断开连接,从机依旧连接到主机的,但是没有写操作,这个时候,主机如果回来了,从机依旧可以直接获取到主机写的信息!
如果是使用命令行,
- 来配置的主从,这个时候如果重启了,就会变回主机!
主机断连
slaveof no one #自己变成老大
info replication
# Replication
role:master
connected_slaves:0
# 如果6380节点,slaveof no one 当做了主节点。
# 6379 又正常运行了,6380 依然是主节点。
# 6379 没有子节点了(谋朝篡位后,真皇帝来了,真皇帝也没有 从节点了)
#如果这个时候老大修复了,那就重新连接
# 即:6380节点,重新当小弟
slaveof 127.0.0.1 6379
实践
启动主节点
- 按照上面的方法 使用配置文件启动 映射本地宿主6379 为主节点
docker run --name redis-test -p 6379:6379 -v $PWD/redis.conf:/etc/redis/redis.conf -v $PWD/data:/data -d redis:latest redis-server ../etc/redis/redis.conf --appendonly yes
更改配置 启动从节点
- 复制2个配置文件,映射宿主接为 6380 和 6381为从节点
#配置文件更改。注意了:这里直接是该配置文件,slaveof命令 只是临时的,主节点是有密码的情况支持吗?
replicaof 192.168.70.127 6379
masterauth 123456
docker run --name redis-6380 -p 6380:6379 -v $PWD/redis.conf:/etc/redis/redis.conf -v $PWD/data:/data -d redis:latest redis-server /etc/redis/redis.conf
#注意:6380:6379 。这里6380是宿主接。6379是Docker容器主机的端口。
docker run --name redis-6381 -p 6381:6379 -v $PWD/redis.conf:/etc/redis/redis.conf -v $PWD/data:/data -d redis:latest redis-server /etc/redis/redis.conf
连接主节点测试
- 连接宿主机的 6379
docker exec -it 75bf41158278 /bin/bash
redis-cli -h localhost -p 6379
auth 123456
info replication #执行此命令,看到2个节点,即代表成功了。
# Replication
role:master
connected_slaves:2
slave0:ip=172.17.0.1,port=6379,state=online,offset=449,lag=0
slave1:ip=172.17.0.1,port=6379,state=online,offset=449,lag=1
master_failover_state:no-failover
master_replid:a1e33fc6d83e88833567a5ddce09d6d89735b254
master_replid2:0000000000000000000000000000000000000000
- 此时docker ps状态
- 可以看到 启动了3个容器,宿主接的6379是 主节点。其他:6380 6381都是从节点。
- Docker容器内的接口都是默认的6379,如果想改其他的 把redis的配置文件 port 6379,改为其他的即可
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8f6cc23342d2 redis:latest "docker-entrypoint.s…" 27 minutes ago Up About a minute 0.0.0.0:6381->6379/tcp, :::6381->6379/tcp redis-6381
75bf41158278 redis:latest "docker-entrypoint.s…" 28 minutes ago Up 6 minutes 0.0.0.0:6380->6379/tcp, :::6380->6379/tcp redis-6380
0930664e31cc redis:latest "docker-entrypoint.s…" 2 days ago Up 2 days 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis-test
哨兵集群
主从缺陷和哨兵
主从切换技术的方法是︰当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预
Redis从2.8开始正式提供了Sentinel(哨兵)架构来解决这个问题。
- 能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。
- 其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
节点 都连接 哨兵:以独立的进程监控3台服务器Redis是否正常运行
- 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
- 还可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
使用Docker安装实践
主节点配置
# 关闭保护模式
protected-mode no
#设置redis端口
port 6379
#设置非守护进程启动,不然跟 docker 的 -d 冲突
daemonize no
# 注释bing采用密码模式访问
#bind 127.0.0.1
#设置主节点的连接密码
masterauth 123456
#外网ip 这个很重要!!!设置本redis的外网访问ip和端口
replica-announce-ip 192.168.70.127
replica-announce-port 6379
#设置redis访问密码
requirepass 123456
从节点配置
- redis端口
- 关联主节点
- 设置本redis的外网访问ip和端口
#设置redis端口
port 6380
#设置关联主节点
replicaof 192.168.70.127 6379
#这个很重要!!!设置本redis的外网访问ip和端口
replica-announce-ip 192.168.70.127
replica-announce-port 6380
# 关闭保护模式
protected-mode no
#设置redis端口
port 6380
#设置非守护进程启动,不然跟 docker 的 -d 冲突
daemonize no
# 注释bing采用密码模式访问
#bind 127.0.0.1
#设置主节点的连接密码
masterauth 123456
#设置关联主节点
replicaof 192.168.70.127 6379
#这个很重要!!!设置本redis的外网访问ip和端口
replica-announce-ip 192.168.70.127
replica-announce-port 6380
#设置redis访问密码
requirepass 123456
主从节点启动
docker run --name redis-6379 -p 6379:6379 -v $PWD/redis.conf:/etc/redis/redis.conf -v $PWD/data:/data -d redis:latest redis-server ../etc/redis/redis.conf --appendonly yes
docker run --name redis-6380 -p 6380:6380 -v $PWD/redis.conf:/etc/redis/redis.conf -v $PWD/data:/data -d redis:latest redis-server ../etc/redis/redis.conf --appendonly yes
docker run --name redis-6381 -p 6381:6381 -v $PWD/redis.conf:/etc/redis/redis.conf -v $PWD/data:/data -d redis:latest redis-server ../etc/redis/redis.conf --appendonly yes
- 如果你的配置文件 /data/redis-1/redis-1.conf 也可以如下配置
docker run --name redis-1 -p 6379:6379 -d -v /data/redis-1:/usr/local/redis redis redis-server /usr/local/redis/redis-1.conf
哨兵配置文件
- 三个哨兵配置文件只要 改动端口 和 外网端口即可
#设置哨兵端口
port 26379
sentinel announce-port 26379
#设置哨兵端口
port 26379
#关闭守护进程启动
protected-mode no
#指定日志位置。这句话得注释,否则容器会报错,说没有这个文件
#logfile "/usr/local/redis/logs/sentinel.log"
#设置本哨兵外网访问ip和端口
sentinel announce-ip 192.168.70.127
sentinel announce-port 26379
#设置监听的主节点地址和最小投票哨兵节点。外网访问ip。因为启动3个哨兵,count设置为了2
sentinel monitor mymaster 192.168.70.127 6379 2
#如果主节点变成了 6381 会自动改。
#设置主节点的连接密码
sentinel auth-pass mymaster 123456
启动3个哨兵Docker
- 在本地 /data下创建目录 sentinel-1 到 3
- 然后在目录下创建 sentinel-1到3.conf
- 使用Docker启动
docker run -d --name=sentinel-1 --privileged=true -p 26379:26379 -v /data/sentinel-1:/usr/local/redis redis redis-sentinel /usr/local/redis/sentinel-1.conf
docker run -d --name=sentinel-2 --privileged=true -p 26380:26380 -v /data/sentinel-2:/usr/local/redis redis redis-sentinel /usr/local/redis/sentinel-2.conf
docker run -d --name=sentinel-3 --privileged=true -p 26381:26381 -v /data/sentinel-3:/usr/local/redis redis redis-sentinel /usr/local/redis/sentinel-3.conf
#也可以增加一个挂载
-v /data/sentinel-3/sentinel-3.conf:/usr/local/redis/sentinel-3.conf
-
关闭6379容器,过一会就会自动进行故障转移了。
- 在打开 6379,会变成从节点
-
节点手动抢占成 master
slaveof no one
config set slave-read-only no
- 关联到 主节点
# 如果master存在密码需要先配置密码
config set masterauth 123456
# 关联master的ip和端口
slaveof 192.168.1.12 6379
使用本地安装实战
sentinel.conf
- 新建配置 sentinel.conf
定义要监控的主节点信息,包括主节点的名称(mymaster)、IP 地址、端口号以及故障转移的最小投票数。
#1代表去投票。注意:不能在1后面加注释.
sentinel monitor myredis 127.0.0.1 6379 1
# 默认的配置文件是这样
#sentinel monitor mymaster 127.0.0.1 6379 2
#sentinel known-replica mymaster 127.0.0.1 6380 默认会发现
#sentinel known-replica mymaster 127.0.0.1 6381
#设置监听的主节点地址和最小投票哨兵节点
#sentinel monitor mymaster 外网访问ip 6379 2
#设置主节点的连接密码
#sentinel auth-pass mymaster 123456
- 最后一个count的意思是有几台 Sentinel 发现有问题,就会发生故障转移,
- 例如 配置为2,代表至少有2个 Sentinel 节点认为主节点不可达,那么这个不可达的判定才是客观的。
- 对于设置的越小,那么达到下线的条件越宽松,反之越严格。一般建议将其设置为 Sentinel 节点的一半加1
本地启动 sentinel
redis-sentinel sentinel.conf #这种是直接前台启动
sudo systemctl restart redis-sentinel.service #重启,也可以stop
- 出现一下,代表哨兵已经正常。
- 发现了:6380 和 6381节点
Running in sentinel mode
79086:X 24 Dec 2023 12:31:25.164 # +monitor master mymaster 127.0.0.1 6379 quorum 1
79086:X 24 Dec 2023 12:31:25.165 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
79086:X 24 Dec 2023 12:31:25.171 * Sentinel new configuration saved on disk
79086:X 24 Dec 2023 12:31:25.171 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
- 关了6379主节点,会把任意一个从节点,变成主节点
service redis-server stop #连接redis后,用shutdown,sentinel会自动启动
- sentinel日志如下
79086:X 24 Dec 2023 12:31:25.171 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
79086:X 24 Dec 2023 12:31:25.178 * Sentinel new configuration saved on disk
79086:X 24 Dec 2023 12:52:20.142 * +reboot master mymaster 127.0.0.1 6379
79086:X 24 Dec 2023 12:54:48.852 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
79086:X 24 Dec 2023 12:54:48.862 * Sentinel new configuration saved on disk
- 查看6380,发现已经变成主节点
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=139368,lag=1
- 6379重启启动,变成从节点
- 如果主机此时回来了,只能归并到新的主机下,当做从机,这就是哨兵模式的规则!
79086:X 24 Dec 2023 13:00:32.838 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
79086:X 24 Dec 2023 13:00:42.832 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
Spring Boot连接
spring boot连接redis 哨兵
yaml配置
spring:
redis:
database: 0
sentinel:
nodes: xxxx.xxxx.xxxx:26381,xxxx.xxxx.xxxx:26380,xxxx.xxxx.xxxx:26379 # 集群哨兵节点配置,多个节点之间用英文逗号分割
master: mymaster # Redis主节点名称,哨兵配置文件中的名称
password: 123456
lettuce:
pool:
max-active: 20
max-wait: 500
max-idle: 10
min-idle: 0
配置连接工厂和序列化
@Configuration
public class RedisConfig {
@Bean
protected LettuceConnectionFactory redisConnectionFactory(RedisProperties redisProperties) {
//获取 哨兵的主节点
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
.master(redisProperties.getSentinel().getMaster());
//设置 哨兵
redisProperties.getSentinel().getNodes().forEach(s -> {
String[] arr = s.split(":");
sentinelConfig.sentinel(arr[0],Integer.parseInt(arr[1]));
});
//密码
sentinelConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));
//redis库选择
sentinelConfig.setDatabase(redisProperties.getDatabase());
//Lettuce 工厂
return new LettuceConnectionFactory(sentinelConfig, LettuceClientConfiguration.defaultConfiguration());
}
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
//redis模板
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
//设置工厂
template.setConnectionFactory(factory);
//jsckson序列化
Jackson2JsonRedisSerializer jacksonJsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//即:存到redis中的对象,必须是 非final
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会抛出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonJsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jacksonJsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jacksonJsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
优缺点
优点︰
1、哨兵集群,基于主从复制模式,所有的主从配置优点,它全有
2、主从可以切换,故障可以转移,系统的可用性就会更好
3、哨兵模式就是主从模式的升级,手动到自动,更加健壮!
缺点︰
1、Redis不好啊在线扩容的,集群容量一旦到达上限,在线扩容就十分麻烦!
2、实现哨兵模式的配置其实是很麻烦的,里面有很多选择!
Redis集群
基本了解
官网教程:https://redis.com.cn/topics/cluster-tutorial.html
RedisCluster 是 Redis 的亲儿子,它是 Redis 作者自己提供的 Redis 集群化方案。
-
去中心化的
-
相互连接组成一个对等的集群,它们之间通过一种特殊的二进制协议相互交互集群信息。
-
将所有数据划分为 16384 的 slots,每个节点负责其中一部分槽位。槽位的信息存储于每个节点中,
-
不需要另外的分布式存储来存储节点槽位信息。
-
每个Redis集群节点需要打开两个TCP连接。端口6379提供给客户端连接,外加上一个端口16379,
槽位定位算法
-
crc32
-
hash
-
16384 取模,得到槽位
-
当客户端向一个错误的节点发出了指令,该节点会发现指令的 key 所在的槽位并不归自己管理,这时它会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,
3主3从
* 架构
客户端
master1 端口:6379。
master2 端口:6380。
master3 端口:6381。
slave1端口:6389
slave2端口:6390
slave3端口:6391
注意:真实搭建时,从节点的主节点 不确定。主节点 默认 任选一个从节点。
比如:我本次搭建的如下:
b5a690e65edbadc0b83858be1a501eea3c8e6fcd 192.168.70.127:6389@16389 slave 775bb3fe63f51b5e9a795d866b1a577647f0e579 0 1703555909000 3 connected
775bb3fe63f51b5e9a795d866b1a577647f0e579 192.168.70.127:6381@16381 master - 0 1703555910942 3 connected 10923-16383
可以看出:6389的主节点是 775bb3fe6,是 6381
停止redis
ps -ef | grep redis | awk -F" " '{print $2;}' | xargs kill -9
下载redis
cd /opt
yum -y install wget
wget https://download.redis.io/redis-stable.tar.gz
安装redis
tar -xzvf redis-stable.tar.gz
cd redis-stable
make install
假如make install报如下异常,直接使用make install MALLOC=libc
安装成功后标志
安装过后你会在src目录中找到几个 Redis 二进制文件,包括:
- redis-server:Redis 服务器本身
- redis-cli:是与 Redis 对话的命令行界面实用程序,客户端。
基本规划和配置
创建cluster目录并且将redis.conf复制到cluster目录
mkdir /opt/redis-stable/cluster
mkdir /opt/redis-stable/cluster/log
cd /opt/redis-stable/cluster
cp /opt/redis-stable/redis.conf /opt/redis-stable/cluster/
6个配置文件的基本更改
port 6379
# 持久化文件
dbfilename dump_6379.rdb
pidfile /var/run/redis_6379.pid
logfile "/opt/redis-stable/cluster/log/6379.log"
# 设置节点配置文件
cluster-config-file node-6379.conf
master
在/opt/redis-stable/cluster/目录创建 redis-6379.conf 文件,内容如下
vim redis-6379.conf #/opt/redis-stable/cluster/redis-6379.conf
bind 0.0.0.0:表示允许所有ip地址访问,
- 默认是127.0.0.1,只允许当前主机连接
include /opt/redis-stable/cluster/redis.conf
# 当我们采用yes时,redis会在后台运行,此时redis将一直运行,除非手动kill该进程。
daemonize yes
bind 0.0.0.0
dir /opt/redis-stable/cluster/
port 6379
dbfilename dump_6379.rdb
pidfile /var/run/redis_6379.pid
logfile "/opt/redis-stable/cluster/log/6379.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6379.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
redis-6380.conf
include /opt/redis-stable/cluster/redis.conf
daemonize yes
bind 0.0.0.0
dir /opt/redis-stable/cluster/
port 6380
dbfilename dump_6380.rdb
pidfile /var/run/redis_6380.pid
logfile "/opt/redis-stable/cluster/log/6380.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6380.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
redis-6381.conf
include /opt/redis-stable/cluster/redis.conf
daemonize yes
bind 0.0.0.0
dir /opt/redis-stable/cluster/
port 6381
dbfilename dump_6381.rdb
pidfile /var/run/redis_6381.pid
logfile "/opt/redis-stable/cluster/log/6381.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6381.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
slave
redis-6389.conf
include /opt/redis-stable/cluster/redis.conf
daemonize yes
bind 0.0.0.0
dir /opt/redis-stable/cluster/
port 6389
dbfilename dump_6389.rdb
pidfile /var/run/redis_6389.pid
logfile "/opt/redis-stable/cluster/log/6389.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6389.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
redis-6390.conf
include /opt/redis-stable/cluster/redis.conf
daemonize yes
bind 0.0.0.0
dir /opt/redis-stable/cluster/
port 6390
dbfilename dump_6390.rdb
pidfile /var/run/redis_6390.pid
logfile "/opt/redis-stable/cluster/log/6390.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6390.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
redis-6391.conf
include /opt/redis-stable/cluster/redis.conf
daemonize yes
bind 0.0.0.0
dir /opt/redis-stable/cluster/
port 6391
dbfilename dump_6391.rdb
pidfile /var/run/redis_6391.pid
logfile "/opt/redis-stable/cluster/log/6391.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6391.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
设置Redis密码 和 集群密码
连接不安全的Redis不能组集群
方式一:在redis.conf配置文件有一个protected-mode默认为yes,设置为no
方式二:在redis.conf配置文件通过requirepass设置密码
- 更改配置文件,关闭所有集群,然后重新启动
- 合并集群指令 加上 -a 123456
添加集群密码,否则 集群某个节点挂掉后,数据无法同步,会拼命打日志
masterauth 123456
启动各个Redis
/opt/redis-stable/src/redis-server /opt/redis-stable/cluster/redis-6379.conf
/opt/redis-stable/src/redis-server /opt/redis-stable/cluster/redis-6380.conf
/opt/redis-stable/src/redis-server /opt/redis-stable/cluster/redis-6381.conf
/opt/redis-stable/src/redis-server /opt/redis-stable/cluster/redis-6389.conf
/opt/redis-stable/src/redis-server /opt/redis-stable/cluster/redis-6390.conf
/opt/redis-stable/src/redis-server /opt/redis-stable/cluster/redis-6391.conf
ps -ef | grep redis
* 组件集群
root@127:/opt/redis-stable/cluster# /opt/redis-stable/src/redis-cli --cluster create --cluster-replicas 1 192.168.70.127:6379 192.168.70.127:6380 192.168.70.127:6381 192.168.70.127:6389 192.168.70.127:6390 192.168.70.127:6391 -a 123456
* 查看集群
/opt/redis-stable/src/redis-cli -c -h 127.0.0.1 -p 6379 -a 123456
127.0.0.1:6379> cluster nodes
a3620ea50164296270d9e23217813580323a7ab8 192.168.70.127:6390@16390 slave f25857941a701d1766716110b92609f79b5ccd9f 0 1703555909936 1 connected
6f29882a70b7742667f8d361548b18e191fd6f1c 192.168.70.127:6391@16391 slave b4123288dbd293c434ced5efa2782a6ebaf9f47b 0 1703555908932 2 connected
b5a690e65edbadc0b83858be1a501eea3c8e6fcd 192.168.70.127:6389@16389 slave 775bb3fe63f51b5e9a795d866b1a577647f0e579 0 1703555909000 3 connected
775bb3fe63f51b5e9a795d866b1a577647f0e579 192.168.70.127:6381@16381 master - 0 1703555910942 3 connected 10923-16383
b4123288dbd293c434ced5efa2782a6ebaf9f47b 192.168.70.127:6380@16380 master - 0 1703555908000 2 connected 5461-10922
f25857941a701d1766716110b92609f79b5ccd9f 192.168.70.127:6379@16379 myself,master - 0 1703555908000 1 connected 0-5460
可以看出:6389的主节点是 775bb3fe6,是 6381
槽位:0-5460,5461-10922,10923-16383
- 16383 / 3= 5461
- 所以索引是:0-5460
- 注意了:这里 你要说 槽位就要说:16384
- 但是你说真实的索引,是从0开始的,最大为 16383,所以:cluster nodes 看到的都是 槽位索引
* 验证集群 设置值
set name ready
-> Redirected to slot [5798] located at 192.168.70.127:6380
OK
明明在 6379 上操作的,但是请求被转发到了6380这个节点去处理了
节点分配
集群至少有3个主节点,因为新master的选举需要大于半数的集群master节点同意才能选举成功
尽量保证每个主库运行在不同的ip,每个主库和从库不在一个ip上,这样才能做到高可用
redis集群 mset的缺陷和解决办法
- 不可以设置,因为不在一个槽位
192.168.70.127:6381> mset a1 v1 a2 v2
(error) CROSSSLOT Keys in request don't hash to the same slot
可以通过{}来定义组的概念,从而使key中{}内相同的键值放到一个slot中去
- 这个样就可以了,因为 都在 g1 分组 所在的槽位
- 注意这里:mset设置后,自动转移到了 6381连接
127.0.0.1:6379> mset a1{g1} aa1 a2{g1} aa2 a3{g1} aa3
-> Redirected to slot [13519] located at 192.168.70.127:6381
OK
192.168.70.127:6381> mget a1{g1}
1) "aa1"
slot命令
cluster keyslot :计算key对应的slot
cluster coutkeysinslot :获取slot槽位中key的个数
cluster getkeysinslot 返回count个slot槽中的键
192.168.70.127:6381> cluster countkeysinslot 13519
(integer) 3
192.168.70.127:6381> cluster getkeysinslot 13519 3
1) "a3{g1}"
2) "a2{g1}"
3) "a1{g1}
客户端工具如何连接
-
如:AnotherRedisDesktopManager
-
勾选上 Cluster,任意一个节点都可以(包括从节点)
-
连接后,都会看到 集群的所有key
- 注意了:如果在 错误的槽位 执行:
keys * (empty array) #是看不到结果的
* 演示故障恢复
如果主节点下线,从节点提升为主节点。
- 注意:要等15秒。用了这个配置
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
root@127:/opt# /opt/redis-stable/src/redis-cli -c -h 127.0.0.1 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> shutdown
not connected>
/opt/redis-stable/src/redis-cli -c -h 127.0.0.1 -p 6380 -a 123456
127.0.0.1:6380> cluster nodes
775bb3fe63f51b5e9a795d866b1a577647f0e579 192.168.70.127:6381@16381 master - 0 1703558363581 3 connected 10923-16383
6f29882a70b7742667f8d361548b18e191fd6f1c 192.168.70.127:6391@16391 slave b4123288dbd293c434ced5efa2782a6ebaf9f47b 0 1703558364585 2 connected
b5a690e65edbadc0b83858be1a501eea3c8e6fcd 192.168.70.127:6389@16389 slave 775bb3fe63f51b5e9a795d866b1a577647f0e579 0 1703558363000 3 connected
a3620ea50164296270d9e23217813580323a7ab8 192.168.70.127:6390@16390 master - 0 1703558363000 7 connected 0-5460
b4123288dbd293c434ced5efa2782a6ebaf9f47b 192.168.70.127:6380@16380 myself,master - 0 1703558360000 2 connected 5461-10922
f25857941a701d1766716110b92609f79b5ccd9f 192.168.70.127:6379@16379 master,fail - 1703558257183 1703558254173 1 disconnected
通过这里的信息,可以看到 6379的 从节点,已经变成了主节点
a3620ea50164296270d9e23217813580323a7ab8 192.168.70.127:6390@16390 master - 0 1703558363000 7 connected 0-5460
- 重新启动 6379,发现 6379 会变成从节点
/opt/redis-stable/src/redis-server /opt/redis-stable/cluster/redis-6379.conf
/opt/redis-stable/src/redis-cli -c -h 127.0.0.1 -p 6379 -a 123456
cluster nodes
f25857941a701d1766716110b92609f79b5ccd9f 192.168.70.127:6379@16379 myself,slave a3620ea50164296270d9e23217813580323a7ab8 0 1703558547000 7 connected
槽位的主从都宕机
redis服务是否还能继续?
这个时候要看 cluster-require-full-coverage 参数的值了
yes(默认值):整个集群都都无法提供服务了
no:宕机的这部分槽位数据全部不能使用,其他槽位正常
- 我们使用redis的主从同步的时候会发现在从机当中set值会异常,因为从机只可以读,
- 而redis集群当中也有主从,但是他可以通过连接从机执行set,不会异常,只会将值存储到指定槽位的主数据库当中。
Redis cluster 优缺点
优点:
- 实现扩容
分摊压力
无中心配置相对简单
高可用,支持集群的主从配置,并且支持主从之间的故障转移
就算主从都挂掉,只会导致部分槽位不可用,其他的仍然可以提供服务!
提供了有关于槽位相关的命令,比如查看指定槽位的key,以及指定向哪个槽位存放数据等。
缺点:
- 多键操作是不被支持的
多键的Redis事务是不被支持的。lua脚本不被支持
由于集群方案出现较晚,很多公司已经采用了其他的集群方案,而代理或者客户端分片的方案想要迁移至redis cluster,需要整体迁移而不是逐步过渡,复杂度较大。
Jedis连接cluster模式
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.4.2</version>
</dependency>
import redis.clients.jedis.*;
import java.util.HashSet;
import java.util.Set;
public class ClusterDemo {
public static void main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
//最大空闲连接数, 默认8个
config.setMaxIdle(8);
//最大连接数, 默认8个
config.setMaxTotal(8);
//最小空闲连接数, 默认0
config.setMinIdle(0);
//获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
config.setMaxWaitMillis(3000);
//在获取连接的时候检查有效性,表示取出的redis对象可用, 默认false
config.setTestOnBorrow(true);
//redis服务器列表
Set<HostAndPort> cluster = new HashSet<>();
// 有多少节点这里就配置多少个
cluster.add(new HostAndPort("192.168.115.239", 6379));
cluster.add(new HostAndPort("192.168.115.239", 6380));
// connectionTimeout连接超时时间,soTimeout读取数据超时,maxAttempts重试次数,password密码
//public JedisCluster(Set<HostAndPort> jedisClusterNode, int connectionTimeout, int soTimeout, int maxAttempts, String password, String clientName, GenericObjectPoolConfig<Jedis> poolConfig) {
JedisCluster jedisCluster = new JedisCluster(cluster, 2000, 2000, 5, "123456", config);
jedisCluster.set("key", "hello world");
String aa1 = jedisCluster.get("aa1");
System.out.println(aa1);
jedisCluster.close();
}
}
SpringBoot整合cluster模式
(1)引入redis的maven配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
(2)application.properties中配置redis sentinel信息
# 集群节点(host:port),多个之间用逗号隔开
spring.redis.cluster.nodes=192.168.115.239:6379,192.168.115.239:6380,192.168.115.239:6381,192.168.115.239:6389,192.168.115.239:6390,192.168.115.239:6391
# 连接超时时间(毫秒)
spring.redis.timeout=60000
spring.redis.password=123456
# Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
database: 0
(3)使用RedisTemplate工具类操作redis
springboot中使用RedisTemplate来操作redis,需要在我们的bean中注入这个对象,代码如下:
@Autowired
private RedisTemplate<String, String> redisTemplate;
// 用下面5个对象来操作对应的类型
this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法
this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法
this.redisTemplate.opsForSet(); //提供了操作set的所有方法
this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法
this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法
(4)RedisTemplate示例代码
@RestController
@RequestMapping("/redis")
public class RedisController {
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* string测试
*
* @return
*/
@RequestMapping("/stringTest")
public String stringTest() {
this.redisTemplate.delete("name");
this.redisTemplate.opsForValue().set("name", "路人");
String name = this.redisTemplate.opsForValue().get("name");
return name;
}
/**
* list测试
*
* @return
*/
@RequestMapping("/listTest")
public List<String> listTest() {
this.redisTemplate.delete("names");
this.redisTemplate.opsForList().rightPushAll("names", "刘德华", "张学友",
"郭富城", "黎明");
List<String> courses = this.redisTemplate.opsForList().range("names", 0,
-1);
return courses;
}
/**
* set类型测试
*
* @return
*/
@RequestMapping("setTest")
public Set<String> setTest() {
this.redisTemplate.delete("courses");
this.redisTemplate.opsForSet().add("courses", "java", "spring",
"springboot");
Set<String> courses = this.redisTemplate.opsForSet().members("courses");
return courses;
}
/**
* hash表测试
*
* @return
*/
@RequestMapping("hashTest")
public Map<Object, Object> hashTest() {
this.redisTemplate.delete("userMap");
Map<String, String> map = new HashMap<>();
map.put("name", "路人");
map.put("age", "30");
this.redisTemplate.opsForHash().putAll("userMap", map);
Map<Object, Object> userMap =
this.redisTemplate.opsForHash().entries("userMap");
return userMap;
}
/**
* zset测试
*
* @return
*/
@RequestMapping("zsetTest")
public Set<String> zsetTest() {
this.redisTemplate.delete("languages");
this.redisTemplate.opsForZSet().add("languages", "java", 100d);
this.redisTemplate.opsForZSet().add("languages", "c", 95d);
this.redisTemplate.opsForZSet().add("languages", "php", 70);
Set<String> languages =
this.redisTemplate.opsForZSet().range("languages", 0, -1);
return languages;
}
/**
* 查看redis机器信息
*
* @return
*/
@RequestMapping(value = "/info", produces = MediaType.TEXT_PLAIN_VALUE)
public String info() {
Object obj = this.redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws
DataAccessException {
return connection.execute("info");
}
});
return obj.toString();
}
kubectl create deployment nginx-deployment --image=nginx --dry-run -o yaml>nginx-deployment.yaml
# 修改 配置文件 或者 执行这个 ,赋值 副本
kubectl scale deployment javademo1 --replicas=3
# 生成 expose的文件
kubectl expose deployment nginx-deployment --name=nginx-service --port=81 --target-port=80 --type=NodePort --dry-run -o yaml>nginx-service.yaml
# 默认 是随机的端口,改配置文件,写死6379也可。
spec:
ports:
- port: 81 #service端口
protocol: TCP
targetPort: 80 #Pod即容器端口
nodePort: 30008 #定义NodePort端口如果不定义会随机生成一个端口
kubectl apply -f nginx-service.yaml
# 查看 随机的端口
kubectl get svc
redis-test NodePort 10.102.207.89 <none> 6379:31646/TCP 41m