Redis持久化
持久化重点!!官网文档:http://www.redis.cn/topics/persistence.html
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是快照,它恢复时是将快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,在用这个临时文件替换上次持久化好的文件,整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。如果需要进行大规模数据恢复,且对数据恢复的完整性不是非常敏感,那么RDB方式要比AOF方式更加高效。RDB的缺点是最后一次持久化数据后的可能会丢失。
RDB
生产环境需要进行备份(dump.rdb
RDB保存的文件是dump.rdb 都是在配置文件中配置的。
#save 60 10000
save 60 5 #测试:60秒内修改 5次 key,就会触发rdb操作
-
save 的规则满足的情况下,会自动触发rdb规则
-
执行flushall命令、也会触发rdb规则
-
退出redis,也会产生rdb文件
恢复:
-
只需要将 rdb文件放在redis启动目录即可,redis启动时会检测dump.rdb恢复其中的数据
-
查看需要存在位置
127.0.0.1:6379> config get dir
1) "dir"
2) "/usr/local/bin" #如果在这个目录下存在dump.rdb 文件,启动时就会自动恢复其中的数据
-
优点:
-
适合大规模的数据恢复!dump.rdb
-
如果对数据完整性要求不高!
-
-
缺点:
-
需要一定的时间间隔进行操作,如果redis意外宕机,最后一次修改数据丢失了
-
fork进程的时候,会占用一定的内存空间。
-
AOF
aof是将所有命令以日志的形式都记录下来,history,将redis执行过得所有指令记录下来,(读操作不记录)。恢复的时候就根据这个日志文件的内容将写指令从头到尾再执行一遍以完成数据的恢复工作。
AOF格式是appendonly.aof文件
默认是不开启的:
appendonly no #默认状态 需要手动开启
# appendfsync always #每次修改都执行、并完成磁盘同步、最安全
appendfsync everysec #每秒执行一次 、并完成磁盘同步
# appendfsync no #从不执行、写入aof文件,不等待磁盘同步、最快
no-appendfsync-on-rewrite no #是否重写、no状态保证数据安全性
#no-appendfsync-on-rewrite参数。如果该参数设置为no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题。如果设置为yes、这就相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。在linux的操作系统的默认设置下,最多会丢失30s的数据。
#因此,如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为yes。如果应用系统无法忍受数据丢失,则设置为no。
把appendonly no 修改 为yes
重启redis服务即可看到appendonly.aof文件
[root@localhost bin]# ls
appendonly.aof redis-check-aof redis-cli redis-sentinel
redis-benchmark redis-check-rdb redis.conf redis-server
如果appendonly.aof文件有问题、服务是起不来的、需要修复aof文件(redis-check-aof)
[root@localhost bin]# redis-cli -p 6379
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected> exit
#修复文件
[root@localhost bin]# redis-check-aof --fix appendonly.aof
0x 8b: Expected prefix '*', got: 'f'
AOF analyzed: size=147, ok_up_to=139, diff=8
This will shrink the AOF from 147 bytes, with 8 bytes, to 139 bytes
Continue? [y/N]: y
Successfully truncated AOF
#测试、成功
[root@localhost bin]# redis-server redis.conf
[root@localhost bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> get kk
"kk"
优点:
-
每一次修改 都同步,文件完整性更可靠
-
默认每秒同步一次,可能会丢失一秒的数据
-
从不同步,效率是最高的
缺点:
-
相对于数据文件来说,aof远远大于rdb,修复速度也比rdb慢!
-
aof运行效率也要比rdb慢,所以默认配置是rdb方式
redis 发布订阅
测试:
订阅端:
127.0.0.1:6379> SUBSCRIBE kobe #订阅一个频道:kobe
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "kobe"
3) (integer) 1
#等待发布信息
1) "message"
2) "kobe"
3) "hello qiangge"
1) "message"
2) "kobe"
3) "zheshi diertiao xinxi"
发布端:
127.0.0.1:6379> PUBLISH kobe "hello qiangge" #发布消息到频道kobe
(integer) 1
127.0.0.1:6379> PUBLISH kobe "zheshi diertiao xinxi" #发布消息到频道kobe
(integer) 1
Redis主从复制
一般来说,将Redis运用到生产环境上,只使用一台redis是不可能的(宕机)。
-
结构上,单个redis服务器会发生单点故障,并且一台服务器需要处理所以请求,负载压力较大。
-
从容量上,单个redis服务器内存容量有限,就算一台redis服务器内存256G,也不能将所有内存做redis的存储,一般来说,单台redis最大使用内存不超过20G。
电商网站上的商品,一般都是一次上传,无数次浏览,就是多读少写。
主从复制,读写分离! 80%都在进行读操作。架构经常使用一主二从!
默认情况下。每台redis服务器都是主节点,且一个主节点可以有多个从节点(或无),但是一个从节点只能有一个主节点!
环境配置
只配置从库,不用配置主库!
127.0.0.1:6379> info replication #查看当前库信息
# Replication
role:master
connected_slaves:0
master_replid:aa439ac9973d1368f702b254d1f91c24512ade9c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
复制三个配置文件,然后修改对应的信息:
-
端口
-
pid名字
-
log文件名字
-
dump.rdb名字
修改完后分别启动三个redis服务。
[root@localhost bin]# ps -ef | grep redis
root 24629 1 0 13:27 ? 00:00:00 redis-server 127.0.0.1:637
root 24657 1 0 13:28 ? 00:00:00 redis-server 127.0.0.1:638
root 24673 1 0 13:28 ? 00:00:00 redis-server 127.0.0.1:638
root 24690 15649 0 13:28 pts/3 00:00:00 grep --color=auto redis
一主二从
默认情况下,每台redis服务器都是主节点;一般配置从机就可以!
主机(79);从机(80/81)
#从机配置
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379 # slaveof host port 认主
OK
127.0.0.1:6380> info replication [section]
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:0
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:1a52f712255b3dc52e458047f619c55651af014b
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:0
#主机查看信息
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=14,lag=0
master_replid:1a52f712255b3dc52e458047f619c55651af014b
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
#配置完两个查看:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=168,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=168,lag=1
master_replid:1a52f712255b3dc52e458047f619c55651af014b
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:168
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:168
真实的主从配置应该在配置文件中配置的。永久生效。命令是暂时配置的!
#配置文件修改(从机)
replicaof <masterip> <masterport> 添加主机 host port 即可
masterauth <master-password> 主机有密码的在这里配置密码
注意:!!
主机可以写,从机不能写只能读。
主机中的所有信息和数据,都会自动被从机保存!
主机断开,从机依旧可以连接到主机,但是不能写。如果主机回来,从机依旧可以获取主机写的信息。
如果是用命令配置的主从,从机断开,就回到master了。
复制原理
Slave 启动成功连接到master后悔发送一个sync同步命令
Master接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,Master将传送整个数据文件到Slave,并完成一次完全同步
全量复制:slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:Master继续将新收集到的修改命令一次传给slave,完成同步。
所以只要是重新连接master,就会执行一次完全同步(全量)。
一主一从(主)一从:
数据可以实现同步、此时中间依旧是从节点、无法写操作。
如果主机断开了,可以使用 Slaveof no one让自己变成主机!其他节点就可以手动连接到这个主节点。(手动)
哨兵模式
(自动选举Master节点)
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理就是哨兵通过命令发送命令,等待Redis服务器的响应,从而监控运行的多个Redis实例。
哨兵的作用:
-
通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
-
当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件.
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
测试:
-
配置哨兵配置文件:sentinel.conf
#sentinel monitor 被监控主机名称 host port 1表示当有一个哨兵发现宕机、就会切换?
sentinel monitor myredis 127.0.0.1 6379 1
-
启动哨兵
[root@localhost bin]# redis-sentinel sentinel.conf
30092:X 18 Sep 2020 15:18:16.476 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
30092:X 18 Sep 2020 15:18:16.476 # Redis version=6.0.8, bits=64, commit=00000000, modified=0, pid=30092, just started
30092:X 18 Sep 2020 15:18:16.476 # Configuration loaded
30092:X 18 Sep 2020 15:18:16.477 * Increased maximum number of open files to 10032 (it was originally set to 1024).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 6.0.8 (00000000/0) 64 bit
.-`` .-```. ```/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 30092
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
30092:X 18 Sep 2020 15:18:16.478 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
30092:X 18 Sep 2020 15:18:16.491 # Sentinel ID is 102ad91558aefe9d2eed0940da97b8226da0c9db
30092:X 18 Sep 2020 15:18:16.491 # +monitor master myredis 127.0.0.1 6379 quorum 1
30092:X 18 Sep 2020 15:18:16.491 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6379
30092:X 18 Sep 2020 15:18:16.492 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6379
如果master节点宕机,这时候就会在从机中选举一个master
#主机宕机、从节点变为master
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=8295,lag=1
master_replid:0db4dfc0339504943a1d434e615071cf2610b3cc
master_replid2:182d395d80b02cac7ad33cd310eb048787ae31ef
master_repl_offset:8427
second_repl_offset:2749
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:8427
#哨兵信息
30092:X 18 Sep 2020 15:22:29.338 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6380
30092:X 18 Sep 2020 15:22:29.338 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ myredis 127.0.0.1 6380
30092:X 18 Sep 2020 15:22:59.347 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ myredis 127.0.0.1 6380
哨兵日志:
如果此时主机修复了。只能做从机,这就是哨兵模式的规则!
哨兵优缺点:
优点:
-
哨兵集群,基于主从复制模式,所有的主从配置优点,他都有。
-
主从可以切换,故障可以转移,系统可用性更好
-
哨兵模式就是主从模式的升级,手动到自动!
缺点:
-
redis不好在线扩容、集群容量一旦到达上限,在线扩容就十分麻烦!
-
实现哨兵模式的配置其实就是很麻烦,里面有很多选择。繁琐!
sentinel monitor <master-name> <ip> <redis-port> <quorum>
告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效
port 端口号
sentinel auth-pass <master-name> <password>
设置连接master和slave时的密码,注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同。
sentinel down-after-milliseconds <master-name> <milliseconds>
这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可用的。 单位是毫秒,默认为30秒
sentinel parallel-syncs <master-name> <numslaves>
这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
sentinel failover-timeout <master-name> <milliseconds>
failover-timeout 可以用在以下这些方面:
1. 同一个sentinel对同一个master两次failover之间的间隔时间。
2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
3.当想要取消一个正在进行的failover所需要的时间。
4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了。
Redis缓存穿透和雪崩
服务器高可用问题!!
缓存穿透:(查询不到)
概念:用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有,于是本次查询失败。当用户很多的时候(秒杀),缓存没有命中,于是都去请求了持久层数据库,这会给持久层数据库造成很大的压力,这个时候就相当于出现了缓存穿透。
解决方案:
-
布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。
-
缓存空对象
当存储层不命中后,既使返回的空对象也将其缓存起来,同时设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端的数据源。
但是这种方法会存在两个问题:
-
如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中会有很多的空值的键。
-
既使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致, 这对需要保持一致性的业务会有影响。
缓存击穿(量太大、缓存过期)
微博服务器宕机(热搜)
这里的和缓存穿透的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像一个屏障上凿开了一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新的数据,并且回写缓存,会导致数据库瞬间压力过大。
解决方案:
-
设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题。
-
加互斥锁
分布式锁:使用分布式锁,保证对每个key同时只有一个线程去查询后端服务其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁分考研很大。
缓存雪崩
缓存雪崩指的是在某一时间段,缓存集中过期失效。redis宕机!
其中集中过期好过于缓存服务器某个节点宕机或者断网。因为在自然形成的雪崩,一定是在某个时间段集中创建缓存,这个时候,数据库也是可以顶住压力的。而缓存服务节点的宕机,对数据服务器造成的压力是不可预知的,可能瞬间就把数据库压垮。
解决方案:
-
redis高可用
搭建集群(异地多活)、其中一台挂掉,其他服务器依旧可以工作
-
限流降级
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
-
数据预热
就是在正式部署之前,先把可能得数据先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
-
停掉一些(不主要)的服务、保证其他服务(主要)的可用。
-