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。