- 1.命令
- 2.redis数据类型指令
- 3.redis.conf 配置
- aof-use-rdb-preamble yes #开启aof 与rdb混合使用
AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将 重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一 起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改 名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。 于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的
AOF 全量文件重放,因此重启效率大幅得到提升。 - 4.sentinel.conf 哨兵高可用架构
- 5.Redis高可用集群搭建
- 6.机器
- 7.redis 配置
1.命令
ps -ef | grep redis #查看正在运行的redis
quit # 退出客户端
./redis-server /soft/redis-5.0.3/etc/redis.conf #单机redis启动命令
/soft/redis-5.0.3/bin/redis-cli -a 123456 —cluster create —cluster-replicas 1 192.168.23.129:8001 192.168.23.129:8002 192.168.23.130:8003 192.168.23.130:8004 192.168.23.131:8005 192.168.23.131:8006 # 集群启动
集群单节点启动
30机器
./redis-server /soft/redis-5.0.3/redis-cluster/8004/redis.conf
./redis-server /soft/redis-5.0.3/redis-cluster/8003/redis.conf
29机器
./redis-server /soft/redis-5.0.3/redis-cluster/8001/redis.conf
./redis-server /soft/redis-5.0.3/redis-cluster/8002/redis.conf
31机器
./redis-server /soft/redis-5.0.3/redis-cluster/8005/redis.conf
./redis-server /soft/redis-5.0.3/redis-cluster/8006/redis.conf
哨兵启动
29 机器
./redis-server /soft/redis-5.0.3/etc/redis.conf
./redis-server /soft/redis-5.0.3/etc/redis-6380.conf
./redis-server /soft/redis-5.0.3/etc/redis-6381.conf
./redis-server /soft/redis-5.0.3/config/sentinel-26379.conf
./redis-server /soft/redis-5.0.3/config/sentinel-26380.conf
./redis-server /soft/redis-5.0.3/config/sentinel-26381.conf
2.redis数据类型指令
String类型结构 | |
---|---|
Redis | RedisTemplate rt |
set key value | rt.opsForValue().set(“key”,”value”) |
get key | rt.opsForValue().get(“key”) |
del key | rt.delete(“key”) |
strlen key | rt.opsForValue().size(“key”) |
getset key value | rt.opsForValue().getAndSet(“key”,”value”) |
getrange key start end | rt.opsForValue().get(“key”,start,end) |
append key value | rt.opsForValue().append(“key”,”value”) |
Hash结构 | |
hmset key field1 value1 field2 value2… | rt.opsForHash().putAll(“key”,map) //map是一个集合对象 |
hset key field value | rt.opsForHash().put(“key”,”field”,”value”) |
hexists key field | rt.opsForHash().hasKey(“key”,”field”) |
hgetall key | rt.opsForHash().entries(“key”) //返回Map对象 |
hvals key | rt.opsForHash().values(“key”) //返回List对象 |
hkeys key | rt.opsForHash().keys(“key”) //返回List对象 |
hmget key field1 field2… | rt.opsForHash().multiGet(“key”,keyList) |
hsetnx key field value | rt.opsForHash().putIfAbsent(“key”,”field”,”value” |
hdel key field1 field2 | rt.opsForHash().delete(“key”,”field1”,”field2”) |
hget key field | rt.opsForHash().get(“key”,”field”) |
List结构 | |
lpush list node1 node2 node3… | rt.opsForList().leftPush(“list”,”node”) rt.opsForList().leftPushAll(“list”,list) //list是集合对象 |
rpush list node1 node2 node3… | t.opsForList().rightPush(“list”,”node”) rt.opsForList().rightPushAll(“list”,list) //list是集合对象 |
lindex key index | rt.opsForList().index(“list”, index) |
llen key | rt.opsForList().size(“key”) |
lpop key | rt.opsForList().leftPop(“key”) |
rpop key | rt.opsForList().rightPop(“key”) |
lpushx list node | rt.opsForList().leftPushIfPresent(“list”,”node”) |
rpushx list node | rt.opsForList().rightPushIfPresent(“list”,”node”) |
lrange list start end | rt.opsForList().range(“list”,start,end) |
lrem list count value | rt.opsForList().remove(“list”,count,”value”) |
rt.opsForList().remove(“list”,count,”value”) | rt.opsForList().set(“list”,index,”value”) |
Set结构 | |
sadd key member1 member2… | rt.boundSetOps(“key”).add(“member1”,”member2”,…) rt.opsForSet().add(“key”, set) //set是一个集合对象 |
scard key | rt.opsForSet().size(“key”) |
sidff key1 key2 | rt.opsForSet().difference(“key1”,”key2”) //返回一个集合对象 |
sinter key1 key2 | t.opsForSet().intersect(“key1”,”key2”)//取相同 |
sunion key1 key2 | rt.opsForSet().union(“key1”,”key2”)//取交集 |
sdiffstore des key1 key2 | rt.opsForSet().differenceAndStore(“key1”,”key2”,”des”) |
sinter des key1 key2 | rt.opsForSet().intersectAndStore(“key1”,”key2”,”des”) |
sunionstore des key1 key2 | rt.opsForSet().unionAndStore(“key1”,”key2”,”des”) |
sismember key member | rt.opsForSet().isMember(“key”,”member”) |
smembers key | rt.opsForSet().members(“key”) |
spop key | rt.opsForSet().pop(“key”) |
srandmember key count | rt.opsForSet().randomMember(“key”,count) |
srem key member1 member2… | rt.opsForSet().remove(“key”,”member1”,”member2”,…) |
3.redis.conf 配置
daemonize yes #后台启动
protected-mode no #关闭保护模式,开启的话,只有本机才可以访问
#bind 127.0.0.1 (bind 是绑定自己的网卡ip,如果有多快网卡可配置多个ip,代表允许客户通过机器的哪些网卡ip可以去访问,内网一般可以不配置bind,注释掉即可)
port 6379 #设置端口号
pidfile /var/run/redis_6380.pid # 把pid进程号写入pidfile配置的文件
logfile “6380.log”
dir /usr/local/redis‐5.0.3/data/6380 # 指定数据存放目录
3.1 RDB 快照
在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中
# save 60 1000 # 60秒执行1000明天 执行rdb快照,保存起来
save与bgsave对比:
命令 | save | bgsave |
---|---|---|
IO类型 | 同步 | 异步 |
是否阻塞redis其它命令 | 是 | (在生成子进程执行调用fork函 数时会有短暂阻塞) |
杂度 | O (n) | o(1) |
优点 | 不会消耗额外内存 | 不阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 需要fork子进程,消耗内存 |
3.2 AOF(append-only file)
AOF 持久化,将修改的每一条指令记录进文件appendonly.aof中(先写入os cache,每隔一段时间 fsync到磁盘)
#appendonly yes #打开 aof 功能
配置多久一次将数据写入磁盘
appendfsync always # 每次有新的命令追加到AOF文件时就执行一次 fsync ,非常慢,但非常安全
appendfsync everysec #每秒 fsync 一次,足够快,并且故障只会丢失一秒的数据
appendfsync no # 从不 fsync ,将数据交给系统来处理,更快,也更不安全的选择
DB 和 AOF ,我应该用哪一个?
命令 | RDB | AOF |
---|---|---|
动优先级 | 低 | 高 |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 容易丢数据 | 根据策略决定 |
生产环境可以都启用,redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof 一般来说数据更全一点
3.3 Redis 4.0 混合持久化
aof-use-rdb-preamble yes #开启aof 与rdb混合使用
AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将 重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一 起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改 名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。 于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的
AOF 全量文件重放,因此重启效率大幅得到提升。
3.4 配置主从复制
replicaof 192.168.0.60 6379 # 从本机6379的redis实例复制数据,Redis 5.0之前使用slaveof
replica‐read‐only yes # 配置从节点只读
4.sentinel.conf 哨兵高可用架构
sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。 哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过 sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis 主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)
1 1、复制一份sentinel.conf文件
2 cp sentinel.conf sentinel‐26379.conf
3
4 2、将相关配置修改为如下值:
5 port 26379
6 daemonize yes
7 pidfile "/var/run/redis‐sentinel‐26379.pid"
8 logfile "26379.log"
9 dir "/usr/local/redis‐5.0.3/data"
10 # sentinel monitor <master‐redis‐name> <master‐redis‐ip> <master‐redis‐port> <quorum>
11 # quorum是一个数字,指明当有多少个sentinel认为一个master失效时(值一般为:sentinel总数/2 +
1),master才算真正失效
12 sentinel monitor mymaster 192.168.0.60 6379 2 # mymaster这个名字随便取,客户端访问时会用
到
13
14 3、启动sentinel哨兵实例
15 src/redis‐sentinel sentinel‐26379.conf
16
17 4、查看sentinel的info信息
18 src/redis‐cli ‐p 26379
19 127.0.0.1:26379>info
20 可以看到Sentinel的info里已经识别出了redis的主从
21
22 5、可以自己再配置两个sentinel,端口26380和26381,注意上述配置文件里的对应数字都要修
4.2 springboot项目核心配置:
server:
2 port: 8080
3
4 spring:
5 redis:
6 database: 0
7 timeout: 3000
8 sentinel: #哨兵模式
9 master: mymaster #主服务器所在集群名称
10 nodes: 192.168.0.60:26379,192.168.0.60:26380,192.168.0.60:26381
11 lettuce:
12 pool:
13 max‐idle: 50
14 min‐idle: 10
15 max‐active: 100
16 max‐wait: 1000
02-VIP-Redis持久化、主从与哨兵架构详解(5).pdf
03-VIP-Redis高可用集群之水平扩展(1).pdf
5.Redis高可用集群搭建
redis集群是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis集群不需 要sentinel哨兵∙也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中 心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点)。redis集群的 性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简
redis集群需要至少三个master节点,我们这里搭建三个master节点,并且给每个master再搭建一个slave节 点,总共6个redis节点,这里用三台机器部署6个redis实例,每台机器一主一从,搭建集群的步骤如下:
第一步:在第一台机器的/usr/local下创建文件夹redis‐cluster,然后在其下面分别创建2个文件夾如下
2 (1)mkdir ‐p /usr/local/redis‐cluster
3 (2)mkdir 8001 8004
4
5 第一步:把之前的redis.conf配置文件copy到8001下,修改如下内容:
6 (1)daemonize yes
7 (2)port 8001(分别对每个机器的端口号进行设置)
8 (3)pidfile /var/run/redis_8001.pid # 把pid进程号写入pidfile配置的文件
9 (4)dir /usr/local/redis‐cluster/8001/(指定数据文件存放位置,必须要指定不同的目录位置,不然会
丢失数据)
10 (5)cluster‐enabled yes(启动集群模式)
11 (6)cluster‐config‐file nodes‐8001.conf(集群节点信息文件,这里800x最好和port对应上)
12 (7)cluster‐node‐timeout 10000
13 (8)# bind 127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通
过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可)
14 (9)protected‐mode no (关闭保护模式)
15 (10)appendonly yes
16 如果要设置密码需要增加如下配置:
17 (11)requirepass zhuge (设置redis访问密码)
18 (12)masterauth zhuge (设置集群节点间访问密码,跟上面一致)
19
20 第三步:把修改后的配置文件,copy到8004,修改第2、3、4、6项里的端口号,可以用批量替换:
21 :%s/源字符串/目的字符串/g
22
23 第四步:另外两台机器也需要做上面几步操作,第二台机器用8002和8005,第三台机器用8003和8006
24
25 第五步:分别启动6个redis实例,然后检查是否启动成功
26 (1)/usr/local/redis‐5.0.3/src/redis‐server /usr/local/redis‐cluster/800*/redis.conf
27 (2)ps ‐ef | grep redis 查看是否启动成功
28
29 第六步:用redis‐cli创建整个redis集群(redis5以前的版本集群是依靠ruby脚本redis‐trib.rb实现)
30 # 下面命令里的1代表为每个创建的主服务器节点创建一个从服务器节点
31 # 执行这条命令需要确认三台机器之间的redis实例要能相互访问,可以先简单把所有机器防火墙关掉,如果不
关闭防火墙则需要打开redis服务端口和集群节点gossip通信端口16379(默认是在redis端口号上加1W)
32 # 关闭防火墙
33 # systemctl stop firewalld # 临时关闭防火墙
34 # systemctl disable firewalld # 禁止开机启动
35 # 注意:下面这条创建集群的命令大家不要直接复制,里面的空格编码可能有问题导致创建集群不成功
36 (1)/usr/local/redis‐5.0.3/src/redis‐cli ‐a zhuge ‐‐cluster create ‐‐cluster‐replicas 1 1
92.168.0.61:8001 192.168.0.62:8002 192.168.0.63:8003 192.168.0.61:8004 192.168.0.62:8005 192.
168.0.63:8006
37
38 第七步:验证集群:
39 (1)连接任意一个客户端即可:./redis‐cli ‐c ‐h ‐p (‐a访问服务端密码,‐c表示集群模式,指定ip地址
和端口号)
40 如:/usr/local/redis‐5.0.3/src/redis‐cli ‐a zhuge ‐c ‐h 192.168.0.61 ‐p 800*
41 (2)进行验证: cluster info(查看集群信息)、cluster nodes(查看节点列表)
42 (3)进行数据操作验证
43 (4)关闭集群则需要逐个进行关闭,使用命令:
44 /usr/local/redis‐5.0.3/src/redis‐cli ‐a zhuge ‐c ‐h 192.168.0.60 ‐p 800* shutdown
5.2 springboot项目核心配置:
1 server:
2 port: 8080
3
4 spring:
5 redis:
6 database: 0
7 timeout: 3000
8 password: zhuge
9 cluster:
10 nodes: 192.168.0.61:8001,192.168.0.62:8002,192.168.0.63:8003,192.168.0.61:8004,192.168.0.
62:8005,192.168.0.63:8006
11 lettuce:
12 pool:
13 max‐idle: 50
14 min‐idle: 10
15 max‐active: 100
16 max‐wait: 1000
6.机器
192.168.23.30 root user02 #账号 密码
192.168.23.29 root user01 #账号 密码
192.168.23.31 root user03 #账号 密码
7.redis 配置
Maxtotal:最大连接数 node(应用个数)*maxTotal不能大于redis的最大链接数maxclients(并发最大执行命令数)
Maxldel 允许最大的空闲链接数,也就是线城池中最小存放的线程数
minldel 资源确保最小的链接数 一般不采用,但是按照Maxldel的线程数来的