redis进阶
一、发布订阅
场景一:(实时性)
直播间中会话,进入直播间之前的消息你是接收不到的,只能接收到进入直播间之后的消息
订阅者只能接收到连接发布者之后发布者发布的消息
场景二:(历史性)
登陆微信之后可以查看历史聊天记录,数据库中肯定存放全量的数据
但是不能全部查库,n天之前的可以查库(请求量特别低),三天内的呢?
zset可以去实现,把时间作为记录的分值,把消息作为元素,按照时间去将数据从redis中删除
左边redis充当发布订阅,当消息来了后讲消息放到右侧redis的zset中。需要查询过往消息的时候从右侧redis读取
二、事务
watch为监听某些key的操作,mutli为开启事务标志
如上图,client1开启了watch监听k1,若client2发送的删除先执行了exec,watch1监听到k1发生了变化,此时client1之后的命令是不执行的
redis是单进程的,client1和client2两个客户端同时发送命令时,会将命令分组放到队列中,哪组命令先出现exec命令就先执行哪组命令,不论事务是否开启
三、布隆过滤器
作用:防止数据穿透
数据穿透了怎么办?在redis中新增一个key,value标记不存在,下次请求再来的时候redis直接返回不存在,避免再次穿透
使用bitmap,如上图:
将数据库中现有的商品依次通过映射函数进行计算,在bitmap中将一些位置标记为1(具体哪些位置进行标记暂不研究)。所有映射函数计算完毕后,bitmap中相应位置都会被进行标记。
元素3为用户请求,当redis中没有该请求的时候使用布隆过滤器,通过映射函数进行计算,当所有计算结果在bitmap中都为1时,放行请求到数据库。
但是此时会有一个问题:请求计算后所有在bitmap中的数字可能都为1(如上图),但是这些被标记为1的bitmap对应的位置可能不是数据库中一个商品计算后修改为1的,这时也会请求到数据库。这种概率很小
四、redis作为缓存和作为数据库的区别
缓存不是全量数据,缓存应该随着访问变化,应该存放热数据
有时会对redis中某一key值设置过期时间,需要明确当查询这一key值时不会延长过期时间,当重新set这一key值时会剔除过期时间
五、管道
1、衔接前一个命令的输出作为后一个命令的输入
2、管道会触发创建子进程
使用linux的时候有父子进程的概念:父类进程的数据子类进程能不能看到?
父子进程修改数据对方看不到。子进程的修改不会破坏父进程,父进程的修改也不会破坏子进程
六、RDB
1、时点性:redis中数据持久化会有一个时间
2、RDB会创建一个子进程,调用fork进行拷贝+copy on write
fork(系统调用)并不是真正的拷贝数据,仅仅是指针指向
进行数据持久化时,父进程(上图fork左下)先通过fork创建一个子进程(上图fork右下),子进程将数据落地到磁盘,子进程创建的时间即为数据落地时间
父进程针对客户端进行操作,子进程进行数据落地
3、命令触发RDB
save触发前台阻塞,不允许对外提供服务,如读写(应用场景比如关机维护)
bgsave触发子进程fork
4、弊端:时点与时点之间容易丢失数据相对多一些
优点:数据写入磁盘,恢复数据速度更快
七、AOF
1、AOF:向文件追加,追加的内容为redis的写操作记录到文件中,类似于mysql中binlog
2、redis中可以同时开启AOF和RDB,如果开启了AOF,只会用AOF恢复
好处:很少丢失数据
弊端:体量无限变大,恢复慢
3、AOF在4.0以后将老的数据RDB到aof文件中,将增量的数据以指令的方式追加到AOF中
AOF是一个混合体,利用了RDB的快
4、redis是内存级别的数据库,写操作会触发IO,写操作有三种级别:
always:每次写入数据都会立即写入磁盘
everysec:redis每秒调一次flush向磁盘中写
no:当redis中数据在内核buffer中满了,会向磁盘中写入
八、AFK原理
1、单机、单节点、单实例的缺陷:
单点故障、容量有限、多线程打进来后压力大
2、AKF从x、y、z三个维度去解决问题
x:解决单点问题,x轴可以创建多个备机,进行数据备份
y:y轴可以将不同的模块数据存放到不同redis中
z:z轴可以建立在同一模块的数据中按照id进行划分出多个redis
3、redis集群保证数据一致性的方案
4、redis一般用主从不用主备,用主从客户端可以访问主节点也可以访问从节点
主备的话客户端是不能访问备机
九、redis主从复制
1、redis主从复制为弱一致性,容易丢失数据
十、redis击穿
redis作为缓存,key过期,或redis中数据被当作冷数据删除,这时高并发过来请求穿过了redis到达数据库
1、解决方案
每一个请求首先get key发现没有,get失败的请求都去setnx,set成功的人去数据库操作,set失败的人睡眠
2、如果set成功的线程挂掉? 可以设置锁的过期时间
3、线程在操作数据库,但是锁过期了? 一个线程取db,一个线程监控是否取回来了,更新锁时间
十一、穿透
业务查询的是数据库中不存在的数据
使用布隆过滤器
十二、雪崩
短时间内大量的key同时失效,间接造成大量请求到达db
可以在业务层加判断进行延时,延时之后随机到达redis