Redis:击穿、雪崩和持久化问题
Redis击穿问题
请求数据顺序,首先会从redis缓存中拿数据,若未拿到则查数据库,再写到redis。如果是请求一条根本不存在的数据时,则会去直接访问数据库,但是数据库也没有,所以它也没把数据写入redis缓存。所以每次这种请求都会直接访问数据库。如果请求的数量太大的话,这种绕过redis直接访问数据库情况则成为击穿。
- 解决方法
1、在查询数据库的时候若未查询到数据,依然在redis中保存一条记录,并把value设置为null或者其他便于区别的值,可以再给该条数据设置一个过期时间,那么以后再有请求过来访问时就不会绕过redis直接去查库。
2、在从redis中获取数据前增加查询校验,对所有可能存在的查询参数缓存到hash集合中,若某个请求在该集合中存在,则可以访问rides,若不存在则直接丢弃该请求。
Redis雪崩问题
每个key(即数据)如果设置了失效时间的话,如果大量key同时过期的时候,或者说因为某种原因redis中的数据突然大批量丢失,这些key又大量地去请求这些key时,因为redis里面没有这些数据,就会大量的请求就会大量涌向数据库,就会导致数据库处理不过来,导致“雪崩”。
- 解决方法
1、设置均匀的过期时间,避免某段时间出现大批量数据失效
2、在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
3、做二级缓存,一级缓存未查询到数据,则从二级缓存查询
链接: 原文地址.
Redis持久化问题
redis有两种持久化方式一种是快照(snapshotting),另一种就是只追加文件(append-only file),通过合理的配置两种持久化方式可以有效的保存内存中的数据,将数据丢失量降到最低。
-
快照(snapshotting):
快照可以将某一时刻的所有数据都写入硬盘中,便于服务器重启后的数据恢复
redis默认开启快照持久化,默认配置为 save 900 1 每900秒有一次数据写入,自动触发bgsave(在后台异步的创建快照进行持久化) - save 300 10 每300秒有10次数据写入,自动触发bgsave
- save 60 10000 每60秒有10000次数据写入,自动触发bgsave
AOF持久化(append-only file):
-
AOF持久化会将被执行的写命令写到AOF文件的末尾,以此记录数据的变化,如若服务器宕机,则从新加载一遍aof文件即可恢复。
appendonly no ->appendonly yes, appendfsync always 每个redis命令都会同步写入硬盘,这样做会严重降低redis的性能,不建议使用
原文:https://blog.csdn.net/qq_36558538/article/details/81588075
Copy On Write
快照原理
我们知道 Redis 是单线程程序,这个线程要同时负责多个客户端套接字的并发读写操作和内存数据结构的逻辑读写。
在服务线上请求的同时,Redis 还需要进行内存快照,内存快照要求 Redis 必须进行文件 IO 操作,可文件 IO 操作是不能使用多路复用 API。
这意味着单线程在服务线上请求的同时,还要进行文件 IO 操作,而文件 IO 操作会严重拖累服务器请求的性能。
还有个重要的问题,为了不阻塞线上的业务,Redis 就需要一边持久化,一边响应客户端的请求。持久化的同时,内存数据结构还在改变,比如一个大型的 hash 字典正在持久化,结果一个请求过来把它给删掉了,可是还没持久化完呢,这该怎么办呢?
Redis 使用操作系统的多进程 COW(Copy On Write)机制来实现快照持久化,这个机制很有意思,也很少人知道。多进程 COW 也是鉴定程序员知识广度的一个重要指标。
fork(多进程)
Redis 在持久化时会调用 glibc 的函数 fork 产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求。子进程刚刚产生时,它和父进程共享内存里面的代码段和数据段。这时你可以把父子进程想象成一个连体婴儿,它们在共享身体。这是 Linux 操作系统的机制,为了节约内存资源,所以尽可能让它们共享起来。在进程分离的一瞬间,内存的增长几乎没有明显变化。
用 Python 语言描述进程分离的逻辑如下。fork 函数会在父子进程同时返回,在父进程里返回子进程的 pid,在子进程里返回零。如果操作系统的内存资源不足,pid 就会是负数,表示 fork 失败。
pid = os.
3ff7
fork()
if pid > 0:
handle_client_requests() # 父进程继续处理客户端请求
if pid == 0:
handle_snapshot_write() # 子进程处理快照写磁盘
if pid < 0:
# fork error
子进程做数据持久化,不会修改现有的内存数据结构,它只是对数据结构进行遍历读取,然后序列化写到磁盘中。但是父进程不一样,它必须持续服务客户端请求,然后对内存数据结构进行不间断的修改。
这个时候就会使用操作系统的 COW 机制来进行数据段页面的分离。如图所示,数据段是由很多操作系统的页面组合而成,当父进程对其中一个页面的数据进行修改时,会将被共享的页面复制一份分离出来,然后对这个复制的页面进行修改。这时子进程相应的页面是没有变化的,还是进程产生时那一瞬间的数据。
随着父进程修改操作的持续进行,越来越多的共享页面被分离出来,内存就会持续增长。但是也不会超过原有数据内存的 2 倍大小。另外一个 Redis 实例里冷数据占的比例往往是比较高的,所以很少会出现所有的页面都会被分离,被分离的往往只有其中一部分页面。每个页面的大小只有 4KB,一个 Redis 实例里面一般都会有成千上万个页面。
子进程因为数据没有变化,它能看到的内存里的数据在进程产生的一瞬间就凝固了,再也不会改变,这也是为什么 Redis 的持久化叫“快照”的原因。接下来子进程就可以非常安心地遍历数据,进行序列化写磁盘了。
- Redis缓存相关问题(雪崩、穿透、击穿、并发)
- 【BigHereo 53】---Redis遇到的问题---雪崩,击穿,穿透
- redis那点事6: 缓存问题篇 (缓存雪崩, 缓存击穿, 缓存穿透等)
- redis击穿和雪崩问题
- Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群
- 解决Redis持久化之大数据服务暂停问题
- 解决Redis持久化之大数据服务暂停问题
- Redis持久化磁盘IO方式及其两种方式带来的问题
- redis 不能持久化问题 MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk.
- Redis缓存穿透、缓存雪崩、redis并发问题分析
- redis-bgrewriteaof问题--持久化恢复问题
- Redis 穿透 击穿 雪崩 认识
- Redis持久化磁盘IO方式及其带来的问题
- Redis持久化——问题定位与优化(三)
- Redis缓存穿透、缓存雪崩、redis并发问题分析
- 关于缓存穿透,缓存击穿,缓存雪崩,热点数据失效问题的解决方案
- 缓存的穿透、击穿、以及雪崩问题的解决方案
- Redis持久化之大数据服务暂停问题
- Redis持久化方式,断电重启读取数据问题
- 解决Redis持久化之大数据服务暂停问题