Redis进阶-----Redis线程模型

1.Redis线程模型

Redis内部使用文件事件处理器file event handler,这个文件事件处理器是单线程的所以redis才叫做单线程的模型。它采用IO多路复用机制同时监听多个socket,将产生事件的socket压入到内存队列中,事件分派器根据socket上的事件类型来选择对应的事件处理器来进行处理。

文件事件处理器包含4个部分:

1.多个socket

2.IO多路复用程序

3.文件事件分派器

4.事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

客户端与redis的一次通信过程:

在这里插入图片描述

1.客户端发起建立连接的请求。

​ 1.1 服务端会产生一个AE_READABLE事件,IO多路复用程序接收到server socket事件后,将该socket压入队列中。

​ 1.2 文件事件分派器从队列中获取socket,交给连接应答处理器,创建一个可以和客户端交流的socket01。

​ 1.3将socket01的AE_READABLE事件与命令请求处理器关联。

2.客户端发起set key value请求。

​ 2.1 socket01产生AE_READABLE事件,socket01压入队列。

​ 2.2 将获取到的socket01与命令请求处理器关联。

​ 2.3 命令请求处理器读取socket01中的key value,并在内存中完成对应的设置。

​ 2.4 将socket01的AE_WRITABLE事件与命令回复处理器关联。

3.服务端返回结果。

​ 3.1 redis中的socket01会产生一个AE_WRITABLE事件,压入到队列中。

​ 3.2 将获取到的socket01与命令回复处理器关联。

​ 3.3 命令回复处理器对socket01输入操作结果,比如ok。之后解除socket01的AE_WRITABLE事件与命令回复处理器的关联。

2.redis单线程效率为什么还很高?

1.纯内存操作。

2.底层是基于非阻塞的IO多路复用机制。

3.C语言实现,距离操作系统更近,执行速度会更快。

4.单线程避免了多线程上下文切换的时间开销,预防了多线程可能产生的竞争问题。

如何保证缓存和数据库的双写一致性

1.常用的缓存+数据库读写方式

1.读数据时,先读缓存,缓存没有,去读数据库,取出数据后放入缓存同时返回响应。

2.更新时,先更新数据库,再删除缓存。

为什么是删除缓存,而不是更新缓存?

1.很多时候缓存不是查出来直接存缓存,而是有一定的逻辑运算,更新成本比较高。

2.需要更新的缓存是否经常被用到,如果没有的话,就不需要进行更新。

2.缓存和数据库信息不一致的问题及解决方案

现象1:先更新数据库,再删除缓存时失败, 就会出现缓存和数据库不一致的现象。

解决方案:先删除缓存、再更新数据库。

现象2:数据发生了变更,先删除了缓存,然后要去修改数据库,此时还没修改。一个请求过来,去读缓存,发现缓存空了,去查询数据库,查到了修改前的旧数据,放到了缓存中。随后数据变更的程序完成了数据库的修改。完了,数据库和缓存中的数据不一样了…

解决方案:

1.需要给数据设置全局唯一ID,确保对该数据的请求能够分发到一台机器上处理。

2.在jvm内部创建一个队列,所有的请求进行串行操作,这样后来的请求就会阻塞起来,不会出现数据不一致的特点。第一个操作执行完成之后,更新了缓存,剩余的请求便可以快速的从缓存中获取。

该方案存在的问题:

1.读请求长时间阻塞。如果数据更新过于频繁的话,会在队列中挤压太多的更新操作,读请求会超时。

2.读请求并发过高。如果同时有很多的读请求打到机器上时,机器不一定能抗住这么高的负载。

3.多服务实例部署的请求路由。必须保证同一商品的读写请求要落在一台机器上。

4.热点商品的路由问题导致请求的倾斜。如果某个商品请求过高,势必会造成某一台机器的负载过高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值