CT处理方案
非法参数进入查询,比如自增的id用-1或者特别大的值来请求,可能是攻击者,这样的请求导致数据库压力变大,严重的时候会击垮数据库
1、对参数设置校验(不信任一切请求参数)
JC处理方案
单个热点key在承受大量并发下当key失效时导致缓存被击穿访问数据库,就像一个完好无损的桶被凿开一个洞
注意:思考key为什么会过期?真的是过期了嘛?真实的情况更多的应该是这个key平常基本上没有被请求,但是突然一波热点导致请求飙升,这个key没有缓存
1、设置热点数据永不过期
2、加互斥锁
XB处理方案
和JC情景类似,是很多个热点key没有缓存,导致大批量并发请求进入DB。
在键值的过期时间失效的一瞬间大量数据直接跨过redis将数据库打死,将数据库重启后又被新的流量给打死导致的数据库瘫痪
1、设置随机值
2、热点数据不设过期时间(在更新时刷新缓存)
缓存预热就是真实的XB、JC的场景,测试时插入了缓存数据,但是上线后各种无法理解的数据请求进来发现没有事先缓存过
导致上面的问题产生
事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
事中:本地 ehcache 缓存 + Hystrix 限流+降级,避免MySQL被打死。
事后:Redis 持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
集群方案
哨兵:
- 集群监控:负责监控master和slave进程是否正常工作
- 消息通知:如果redis有故障,负责提供报警消息
- 故障转移:如果master node挂了,会自动转移到slave node上
- 配置中心:故障转移后会通知client客户端新的matser地址
哨兵特点与zk特点很像,需要3个实例来保证自己健壮性,只满足CAP理论中的AP,不能保证数据零丢失,只能保证高可用和系统分区容错性
集群:
通过hash方式将数据分片,数据先写入主节点再同步到从节点,异步复制
主从:
一主多从,住负责写,从负责读
持久化
**RDB:**某一时刻全量数据的副本(将内存某一时刻的记录的数据序列化至磁盘)
特点:丢失的数据会比较多,但是恢复的速度快
**AOF:**日志,append到文件上的日志
特点:数据完整,但是慢,需要重现所有指令,而且体积比较大(日志冗余,相同的key做重复操作)
三个写入级别:
1、每操作都append日志中,串行立刻记录(性能最差,破坏了redis的初衷—快)
2、默认级别每秒中刷写
3、留给操作系统的内核缓冲区,缓冲区满了就往日志中刷写
默认开启RDB,如果开启了AOF此时RDB就会失效
混合使用:RDB做全量,AOF做增量,4.0之后在rdb文件中加入AOF做增量
实际操作:vi /etc/redis/6379.conf
将配置文件中只bind绑定本地地址的配置注释掉
将protected-mode no改成yes,否则别人无法连接进来
关掉RDB:save的三个参数注释,然后写成save “”
appendonly开启
三种append级别:
appendfsync always()
appendfsync everysec
appendfsync no
单线程
内部使用文件事件处理器 file event handler,这个处理器是单线程的,所以redis才是单线程的模型,它采用IO多路复用机制同时监听多个Socket,根据Socket事件来选择对应的事件处理器禁行处理
文件事件处理器的结构包含4个部分:
- 多个Socket
- IO多路复用程序
- 文件事件分派器
- 事件处理器
多个Socket可能会并发产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个Socket,会将Socket产生的事件放入队列中排队 ,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器禁行处理
Q:Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?
A:使用keys指令可以扫描出指定模式的key列表
Q:如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?
A:redis是单线程的,使用keys命令会占用运行线程,线上服务停顿,直至命令执行完毕服务才能恢复。可以使用scan命令,线程无阻塞取出指定模式key列表,但是有一定重复概率,客户端再做一次去重就可以了,但是花费时长要比keys长
redis是如何删除过期key的
1、后台在轮询分段分批的删除过期key
2、请求的时候判断是否已经过期了
缓存是如何淘汰的
0、内存空间不足的情况下
1、淘汰机制里不允许淘汰
2、lru/lfu/random/TTL
3、全空间
4、设置过期key的集合中
缓存预热
1、提前把数据塞入redis(引伸出问题:哪些是热数据?),当上线后没有缓存命中的数据就会导致XB、JC的故障
2、开发逻辑上也要规避差集(没有预热的数据)----实施加锁解决
3、好处一劳永逸,未来也不怕了
Y&Q
-
读写性能:读110000qps,写81000qps
-
持久化:AOF和RDB
-
事务:都是原子性
-
数据结构丰富
-
支持主从
-
容易收到物理内存的限制,不能用作海量数据的高性能读写,一般用在小数据量的高性能操作运算上
-
不具备自动容错和恢复功能
-
主机宕机前未同步的数据,切换后引入数据不一致的问题,降低了系统的可用性
-
在线扩容复杂,需要提前备份较大的空间,浪费资源
主从不一致问题
1、redis默认是弱一致性,主从是异步的同步,所以肯定是有不一致的问题
2、锁不能用主从集群(单实例/分片集群/redlock)==>redisson解决
如何保证双写一致性:
可以使用分布式事务来解决,但是意义不大(情况是读多,写稀有)
1、redis是缓存,更倾向于更新稍微有时差。涉及到硬件存储就避免不了时差
2、最好还是减少DB操作
3、如果需要落地实现可以使用canal
延时双删
- 为什么要先删除缓存再更新数据库:
保证在更新数据库后无论接下来操作缓存的时候成不成功都不会读到脏数据 - 但是先删后更也会又问题,如下图:
虽然出现的记录很小,但是也是有可能会发生的!
总结:先删是为了更新后再删除缓存会失败;而双删是为了保证更新时先删掉缓存后这时进来一个读的操作,而读空后赋值给缓存若比更新操作执行的更快的话就还是会导致数据不一致的情况,如果第二次再删除的时候不幸失败了,那就将删除的操作放进消息队列中让它重复删除直至成功为止