redis的两种持久化方案:从应用到底层 36张图带你进入Redis世界
redis的两种持久化方案:从应用到底层 36张图带你进入Redis世界4、Redis在执行BGSAVE和BGREWRITEAOF命令时,哈希表的负载因子>=5,而未执行这两个命令时>=1。目的是尽量减少写操作,避免不必要的内存写入操作。3、配置牛逼点,合理配置Linux的内存分配策略,避免因为物理内存不足导致fork失败。关于Fork的建议:1、降低fork的频率,比如可以手动来触发RDB生成快照、与AOF重写;2、控制Redis最大使用内存,防止fork耗时过长;
1、在重写期间,由于主进程依然在响应命令,为了保证最终备份的完整性;它依然会写入旧的AOF中,如果重写失败,能够保证数据不丢失。
2、为了把重写期间响应的写入信息也写入到新的文件中,因此也会为子进程保留一个buf,防止新写的file丢失数据。
3、重写是直接把当前内存的数据生成对应命令,并不需要读取老的AOF文件进行分析、命令合并。
4、无论是 RDB 还是 AOF 都是先写入一个临时文件,然后通过rename完成文件的替换工作。
关于Fork的建议:
1、降低fork的频率,比如可以手动来触发RDB生成快照、与AOF重写;
2、控制Redis最大使用内存,防止fork耗时过长;
3、配置牛逼点,合理配置Linux的内存分配策略,避免因为物理内存不足导致fork失败。
4、Redis在执行BGSAVE和BGREWRITEAOF命令时,哈希表的负载因子>=5,而未执行这两个命令时>=1。目的是尽量减少写操作,避免不必要的内存写入操作。
5、哈希表的扩展因子:哈希表已保存节点数量 / 哈希表大小。因子决定了是否扩展哈希表。
2.3、恢复启动时会先检查AOF(数据更完整)文件是否存在,如果不存在就尝试加载RDB。
2.4、建议既然单独用RDB会丢失很多数据。单独用AOF,数据恢复没RDB来的快,所以出现问题了第一时间用RDB恢复,然后AOF做数据补全才说王道。
3、Redis为什么那么快3.1、 基于内存实现:数据都存储在内存里,相比磁盘IO操作快百倍,操作速率很快。
3.2、高效的数据结构:Redis底层多种数据结构支持不同的数据类型,比如HyperLogLog它连2个字节都不想浪费。
3.3、丰富而合理的编码:Redis底层提供了 丰富而合理的编码 ,五种数据类型根据长度及元素的个数适配不同的编码格式。
1、String:自动存储int类型,非int类型用raw编码。
2、List:字符串长度且元素个数小于一定范围使用 ziplist 编码,否则转化为 linkedlist 编码。
3、Hash:hash 对象保存的键值对内的键和值字符串长度小于一定值及键值对。
4、Set:保存元素为整数及元素个数小于一定范围使用 intset 编码,任意条件不满足,则使用 hashtable 编码。
5、Zset:保存的元素个数小于定值且成员长度小于定值使用 ziplist 编码,任意条件不满足,则使用 skiplist 编码。
3.4、合适的线程模型:I/O 多路复用模型同时监听客户端连接,多线程是需要上下文切换的,对于内存数据库来说这点很致命。
3.5、 Redis6.0后引入多线程提速:要知道 读写网络的read/write系统耗时 >> Redis运行执行耗时,Redis的瓶颈主要在于网络的 IO 消耗 优化主要有两个方向:
1、提高网络 IO 性能,典型的实现比如使用 DPDK 来替代内核网络栈的方式
2、使用多线程充分利用多核,典型的实现比如 Memcached。
协议栈优化的这种方式跟 Redis 关系不大,支持多线程是一种最有效最便捷的操作方式。所以Redis支持多线程主要就是两个原因:
1、可以充分利用服务器 CPU 资源,目前主线程只能利用一个核
2、多线程任务可以分摊 Redis 同步 IO 读写负荷
关于多线程须知:
Redis 6.0 版本 默认多线程是关闭的 io-threads-do-reads no
Redis 6.0 版本 开启多线程后 线程数也要 谨慎设置。
多线程可以使得性能翻倍,但是多线程只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行。
4、常见问题4.1、缓存雪崩雪崩定义:
Redis中大批量key在同一时间同时失效导致所有请求都打到了MySQL。而MySQL扛不住导致大面积崩塌。
雪崩解决方案:
1、缓存数据的过期时间加上个随机值,防止同一时间大量数据过期现象发生。
2、如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
3、设置热点数据永远不过期。
4.2、缓存穿透穿透定义:
缓存穿透 是 指缓存和数据库中都没有的数据,比如ID默认>0,黑客一直 请求ID= -12的数据那么就会导致数据库压力过大,严重会击垮数据库。
穿透解决方案:
1、后端接口层增加 用户鉴权校验,参数做校验等。
2、单个IP每秒访问次数超过阈值直接拉黑IP,关进小黑屋1天,在获取IP代理池的时候我就被拉黑过。
3、从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null 失效时间可以为15秒防止恶意攻击。
4、用Redis提供的 Bloom Filter 特性也OK。
4.3、缓存击穿击穿定义:
现象:大并发集中对这一个热点key进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库。
击穿解决:
设置热点数据永远不过期 加上互斥锁也能搞定了
4.4、双写一致性双写:缓存跟数据库均更新数据,如何保证数据一致性?
1、先更新数据库,再更新缓存
安全问题:线程A更新数据库->线程B更新数据库->线程B更新缓存->线程A更新缓存。导致脏读。
业务场景:读多写少场景,频繁更新数据库而缓存根本没用。更何况如果缓存是叠加计算后结果更浪费性能。
2、先删缓存,再更新数据库
A 请求写来更新缓存。
B 发现缓存不在去数据查询旧值后写入缓存。
A 将数据写入数据库,此时缓存跟数据库不一致。
因此 FackBook 提出了 Cache Aside Pattern
失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
命中:应用程序从cache中取数据,取到后返回。
更新:先把数据存到数据库中,成功后,再让缓存失效。
4.5、脑裂