Redis 持久化机制
Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。
实现:1,父进程调用fork(),创建子进程;2,将当前父进程的数据库数据复制到子进程的内存中;3,子进程将数据写入到临时文件中,持久化的过程结束;4,再用这个临时文件替换上次的快照文件;5,子进程退出,内存释放。
RDB:
Redis默认的持久化方式。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。即Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。
优点:
1 适合大规模的数据恢复。
2 如果业务对数据完整性和一致性要求不高,RDB是很好的选择。
缺点:
不支持实时,存在版本兼容问题,意外挂机会丢失最后一次快照前的数据。
关闭RDB:注释掉下面配置,并打开save "" 的注释
save 900 1:表示900 秒内如果至少有 1 个 key 的值变化,则保存; save 300 10:表示300 秒内如果至少有 10 个 key 的值变化,则保存; save 60 10000:表示60 秒内如果至少有 10000 个 key 的值变化,则保存;
AOF
Redis会将每一个收到的写命令都通过Write函数追加到文件最后,类似于MySQL的binlog。当Redis重启是会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
打开AOF方法:进入redis.conf,配置appendonly为yes
优点:数据的完整性和一致性更高
缺点:因为AOF记录的内容多,文件会越来越大,数据恢复也会越来越慢。
当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。
缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题
缓存雪崩
大面积缓存过期,导致所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力
解决:加锁排队,数据预热,永不过期,时效时间分散
缓存穿透
查询缓存和数据库中都不存在的数据,导致每次都访问完缓存再访问数据库
解决:使用 Guava 的布隆过滤器;把空结果进行短暂的缓存
缓存预热
将热点数据定时或人工操作,缓存到缓存系统,供用户查询
缓存降级
服务降级是当服务器压力剧增的情况下,释放服务器资源以保证核心任务的正常运行。
根据服务方式:可以拒接服务,可以延迟服务,也有时候可以随机服务。
根据服务范围:可以砍掉某个功能,也可以砍掉某些模块。
热点数据&冷数据
热点:商品数据(首页,商详,销量),用户数据
冷数据:历史订单信息等
Memcache与Redis的区别
1)、Memecache不支持持久化
2)、数据支持类型 memcached仅支持k-v,redis作为其替代者,支持更为丰富的数据类型 ,提供list,set,zset,hash等数据结构的存储
3)、使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4)、redis性能更好(这点不是很确定,要看情况)
5)、redis功能更多,大多数情况可能会选择redis
单线程的redis为什么这么快
(1)纯内存操作
(2)单线程操作,避免了频繁的上下文切换
(3)采用了非阻塞I/O多路复用机制
redis数据类型使用场景
String: 这个其实没啥好说的
Hash:这里value存放的是结构化的对象,比如用户信息。
List:使用List的数据结构,可以做简单的消息队列的功能。
set:因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。
sorted set:多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。
Redis 内部结构
dict:类似字典表;sds:存储任意二进制数据;skiplist (跳表)、quicklist、ziplist(压缩表)
redis的过期策略以及内存淘汰机制
定期删除:redis默认每个100ms检查(随机抽取),是否有过期的key,有过期key则删除
惰性删除:获取某个key的时候,判断是否过期
内存淘汰机制:
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据,新写入操作会报错
Redis 为什么是单线程的
官方FAQ表示,因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了(毕竟采用多线程会有很多麻烦!)
IO多路复用技术
举个例子,模拟一个tcp服务器处理30个客户socket。
假设你是一个老师,让30个学生解答一道题目,然后检查学生做的是否正确,你有下面几个选择:
第一种选择:按顺序逐个检查,先检查A,然后是B,之后是C、D。。。这中间如果有一个学生卡主,全班都会被耽误。这种模式就好比,你用循环挨个处理socket,根本不具有并发能力。
第二种选择:你创建30个分身,每个分身检查一个学生的答案是否正确。 这种类似于为每一个用户创建一个进程或者线程处理连接。
第三种选择,你站在讲台上等,谁解答完谁举手。这时C、D举手,表示他们解答问题完毕,你下去依次检查C、D的答案,然后继续回到讲台上等。此时E、A又举手,然后去处理E和A。。。 这种就是IO复用模型
线程模型:
Redis 集群
主从模式(redis2.8版本之前的模式)、哨兵sentinel模式(redis2.8及之后的模式)、redis cluster模式(redis3.0版本之后)
对于大量的请求怎么样处理
redis是一个单线程程序,也就说同一时刻它只能处理一个客户端请求;
redis是通过IO多路复用(select,epoll, kqueue,依据不同的平台,采取不同的实现)来处理多个客户端请求的
Redis 常见性能问题和解决方案
(1) Master 最好不要做任何持久化工作,如 RDB 内存快照和 AOF 日志文件
(2) 如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一次
(3) 为了主从复制的速度和连接的稳定性, Master 和 Slave 最好在同一个局域网内
(4) 尽量避免在压力很大的主库上增加从库
(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即: Master <- Slave1 <- Slave2 <-Slave3…
原文链接:https://blog.csdn.net/Butterfly_resting/article/details/89668661