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、可以批量执行一组指令,一次性返回全部结果

六、RDB

1、时点性:redis中数据持久化会有一个时间

2、RDB会创建一个子进程,调用fork进行拷贝+copy on write

  fork(系统调用)并不是真正的拷贝数据,仅仅是指针指向

 

 进行数据持久化时,父进程(上图fork左下)先通过fork创建一个子进程(上图fork右下),子进程将数据落地到磁盘,子进程创建的时间即为数据落地时间

 父进程针对客户端进行操作,子进程进行数据落地

3、命令触发RDB

  save触发前台阻塞,不允许对外提供服务,如读写(应用场景比如关机维护)

  bgsave触发子进程fork

 4、弊端:RDB都是快照文件,都是默认五分钟或更久的时间生成一次,这就意味着这次同步到下次同步中间五分钟的数据可能全部丢失

      优点:数据写入磁盘,恢复数据速度更快

 七、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中满了,会向磁盘中写入

 八、AKF原理

1、单机、单节点、单实例的缺陷:

  单点故障、容量有限、多线程打进来后压力大

2、AKF从x、y、z三个维度去解决问题

  x:解决单点问题,x轴可以创建多个备机,进行数据备份

  y:y轴可以将不同模块(按照业务区分模块)数据存放到不同redis中

  z:z轴可以建立在同一模块的数据中按照id进行划分出多个redis

 

 3、redis集群保证数据一致性的方案

 4、redis一般用主从不用主备,用主从客户端可以访问主节点也可以访问从节点

  主备的话客户端是不能访问备机

 九、redis主从复制

redis主从复制为弱一致性,容易丢失数据,异步复制数据,可用性较高

你启动一台slave 的时候,他会发送一个psync命令给master ,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,master会将这个RDB发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存里面缓存的那些新命名都发给slave。

十、哨兵

1、哨兵监听master判断是否可用,若不可用,重新选举master,之后让其他节点重新连接新的master

2、哨兵中会配置master的ip和端口号,master会往从节点同步数据,所以哨兵也知道从节点的端口号

3、哨兵之间彼此互相知道是通过发布订阅原理

4、哨兵的作用:监听、通知、自动转移故障

  监听主节点是否可用

  通知:哨兵监听的服务器出现问题时会通知其他哨兵

  自动转移故障:在从机中重新选举master

 十一、redis击穿

redis作为缓存,key过期,或redis中数据被当作冷数据删除,这时高并发过来请求穿过了redis到达数据库

1、解决方案

  每一个请求首先get key发现没有,get失败的请求都去setnx,set成功的人去数据库操作,set失败的人睡眠

2、如果抢到setnx的线程在操作数据库的时候挂掉,导致其他线程一直阻塞无法获取value?  可以设置锁的过期时间

3、线程正在操作数据库,但是设置的超时时间过短,锁过期了,下一个线程到达数据库?  一个线程取db,一个线程监控是否取回来了,更新锁时间

十二、穿透

业务查询的是数据库中不存在的数据

使用布隆过滤器

十三、雪崩

短时间内大量的key同时失效,间接造成大量请求到达db

可以在业务层加判断进行延时,延时之后随机到达redis

 十四、分布式锁

分布式锁一般使用zookeeper,虽然redis快,但是既然上锁了,就不会要求效率特别高。也就是说不要求速度快,要求一致性

1、redis:setnx+过期时间+多线程(守护线程)延长过期

  首先setnx去设置key,如果redis中key不存在时,设置key值,否则设置失败(谁先抢到锁)

  过期时间:①过期时间到了,活没干完  

        当线程setnx抢到锁后去进行后面的操作(比如往一个文件中写数据),操作还没执行完,分布式锁过期了,这时下一线程会抢到锁同样往一个文件中写数据,这时可能产生脏数据

       ②时间没到,线程挂了

  增加守护线程:用于判断抢到锁的线程是否执行完业务逻辑,避免因设置的过期时间较短发生的错误

2、zookeeper做分布式锁

两个客户端去抢占锁,拿到锁之后才有资格去访问资源

1、抢占锁

2、获得锁的人出现问题:临时节点,session消失,临时节点消失

3、锁被释放别人怎么知道?

  ①客户端去轮询锁,看锁是否被释放。

    轮询:发送心跳。弊端:有延迟、当有多个客户端一同向锁发送心跳会造成压力过大

    watch:解决了延迟,但是若客户端过多,需要发送心跳的客户端也很多,压力过大

    顺序节点+watch:每一个请求锁的客户端在父目录下创建顺序临时节点(有编号顺序),watch前一个顺序临时节点,解决了压力过大问题 

 

 

 

 

 

 

 

 

 

 

 

  

 

posted @ 2022-02-20 19:18  showMeTheCodes  阅读(118)  评论(0编辑  收藏  举报