导图社区 Redis脑图
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
编辑于2021-08-18 21:53:56Redis
应用场景
1、秒杀库存扣减
2、APP首页的访问流量高峰
3、与memCache的区别
基础知识
数据结构
5种基本数据结构:String 、Hash、List、Set、SortedSet
其他数据结构:HyperLongLong、Geo、Pub/Sub
用于防止缓存击透的数据机构:Redis Module,像BloomFilter,RedisSearch,Redis-ML
设置key值过期:setRedis(Key , value, time+Math.random()*10000); expire;
分布式锁
先拿setnx来争抢锁,抢到后,再用expire给锁一个过期时间防止锁忘了释放
如果在setnx之后执行expire之前进程意外crash或者要重启维护,把setnx和expire合成一条指令来用的
Keys命令
Redis的单线程的,keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复
scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端左一次去重就可以了,但是整体所花费的时间会比直接用keys指令长
SMEMBERS命令可以返回集合键当前包含的所有元素
SCAN这些增量式迭代命令来说,因为在对键进行增量迭代的过程中,键可能会被修改,所以增量式迭代命令只能对被返回的元素提供有限的保证。
异步队列
list结构作为队列,rpush产生消息,lpop消费消息。当lpop没有消息来的时候,要适当sleep一会再试。
list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。
pub/sub主题订阅者模式,可以实现1:N的消息队列,实现生产一次,消费多次
pub/sub主题订阅者模式,消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如RocketMQ
延时队列
sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。
持久化
RDB做镜像全量持久化,AOF做增量持久化。因为RDB会消耗较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要AOF来配合使用。在redis实例重启时,会使用RDB持久化文件重新构建内存,再使用AOF重放近期的操作指令来实现完整恢复重启之前的状态。
Redis本身的机制式AOF持久化开启且存在AOF文件时,优先加载AOF文件;AOF关闭或者AOF文件不存在时,加载RDB文件;加载AOF/RDB文件后,Redis启动成功;AOF/RDB文件存在错误是时,Redis启动失败并打印错误信息。
机器断电对数据丢失的影响
AOF日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s一次,这个时候最多就会丢失1s的数据。
RDB原理
Fork是指redis通过创建子进程来进行RDB操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
Pipeline好处
可以将多次IO往返的时间缩短为一次,前提是pipeline执行的指令之间没有因果相关性
集群的同步机制
Redis可以使用主从同步,从从同步
第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将RDB文件全量同步到复制节点
复制节点接受完成后将RDB镜像加载到内存,加载完成后,再通知主节点。
后续的增量数据通过AOF日志同步即可,有点类似数据库的binlog
集群的高可用
Redis Sentinal 着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储
缓存雪崩、击穿、穿透
雪崩
大面积的缓存失效,打崩了DB
同一时间大面积失效,那一瞬间Redis跟没有一样,那这个数量级别的请求直接打到数据库几乎是灾难性的,你想想如果打挂的是一个用户服务的库,那其他依赖他的库所有的接口几乎都会报错,如果没做熔断等策略基本上就是一瞬间挂一片的节奏
解决办法
1、批量往Redis存数据的时候,把每个Key的失效时间都加个随机值就好了,这样就可以保证数据不会在同一时间大面积失效
2、Redis是集群部署,将热点数据均匀分布在不同的Redis库中也能避免全部失效的问题
3、设置热点数据永远不过期,有更新操作就更新更新缓存就好了
穿透
用户不断的发起缓存和数据库中均不存在的数据的请求,导致数据库压力过大,严重会击垮数据库
解决办法
1、增加参数校验
2、从网关层Nginx增加配置项,对单个IP每秒访问次数超出阈值的IP都拉黑
3、布隆过滤器(Bloom Filter)这个也能很好的防止缓存穿透的发生,它的原理也很简单就是利用高效的数据结构和算法快速判断出你这个key是否在数据库存在,不存在你return 就好了,存在你就去查了DB刷新KV再return
击穿
一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞
解决办法
1、设置热点数据永不过期
2、增加互斥锁
持久化
RDB
冷备
RDB持久化机制,是对Redis中的数据执行周期性的持久化
优点:RDB对Redis的性能影响非常小,是因为在同步数据的时候他只是fork了一个子进程去做持久化的,而且他在数据恢复的时候速度比AOF来的快。
缺点:RDB都是快照文件,都是默认五分钟甚至更久的时间才会生产一次,这意味着你这次同步到下次同步这中间五分钟的数据都很有可能全部丢掉,AOF则最多丢一秒的数据;RDB在生成数据快照的时候,如果文件很大,客户端可能会暂停几毫秒甚至几秒
AOF
热备
AOF机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中
优点:AOF是一秒一次去通过一个后台的线程fsync操作,那最多丢这一秒的数据。AOF在对日志文件进行操作的时候是以append-only的方式去写的,他只是追加的方式写数据,自然就少了很多磁盘寻址的开销。
缺点:一样的数据,AOF文件比RDB还要大
哨兵
哨兵+主从 实现redis集群高可用
集群监控:负责监控 Redis master和 slave 进程是否正常工作
消息通知:如果某个Redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员
故障转移:如果master node 挂掉了,会自动转移到slave node上
配置中心:如果故障转移发生了,通知client客户端新的master地址。
主从同步
启动一台slave的时候,他会发送一个psync命令给master,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,master会将这个RDB发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存里面缓存的那些新命名都发给slave。
内存淘汰机制
分布式锁
最经典的KV、DB读写模式
与memcache区别
学习思路