分布式缓存的主要有点: 高性能与高并发
高性能:内存读取速度远高于数据库
高并发:数据库瞬间不能支持高并发,通过缓存,可以支持每秒十万级的请求。普通数据库每秒响应千级的。
使用缓存存在的常规问题:
1.缓存与数据库双写不一致 先删缓存,然后写db,在删除缓存。
2.缓存雪崩 缓存集群挂了,或者大量缓存同一时间过期的导致大量请求打到db。保证缓存集群的高可用, 哨兵或者cluster方案。热点key不要过去,定时去更新。热点key分部在cluster的不同节点上。
3.缓存击穿 一个缓存key失效的瞬间,大量请求进入db。 做限流,分布式锁,只允许一个请求去查询db。
4.缓存穿透 大量cache中不存在这个key,请求进入db。 可以在db中查询没有的key,在cache中设置一个快速过期的空值。或者使用布隆过滤器,把所有可能存的数据存在一个足够大的bitmap中,一定不存在的数据就会被拦截在,从而避免对底层数据库的查询。
redis的线程模型:
redis基于reactor模式开发了网络事件处理模型,这个事件叫做文件事件处理模型(file event handler)。这个文件处理器是单线程的,采用IO多路复用机制同时监听多个socket,根据socket上的事件来选择对应事件处理器来处理这个事件。
文件事件处理器是单线程运行的,但是通过IO多路复用机制来监听多个socket,可以实现高性能的网络通信模型,又可以和内部其他单线程的模块进行对接,保证了redis内部的线程模型的简单性。
文件事件处理包含四个部分:多个socket,IO多路复用程序,文件事件分派器,事件处理器(命令请求处理器,命令回复处理器,连接答应处理器等等)。
多个socket可能并发的产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用机制会监听多个socket,但是会将socket放入一个队列中进行排队,每次从队列中取出一个socket给事件分派器,事件分派器把socket给对应的事件处理器。然后一个socket的事件处理完成之后,IO多路复用程序才会将队列中的下一个socket给事件分配器,事件分配器把socket给具体的事件处理器。
客户端与redis通信的一次流程。
Redis的客户端对服务端的每次调用都经历了发送命令,执行命令,返回结果三个步骤。其中执行命令阶段,由于redis是单线程来处理命令的,所以每条到达服务端的命令不会立即被执行,所有命令会进入一个队列然后逐个被执行。多个客户端发送的命令的执行顺序是不确定的,但是可以确定的是两个命令不会被同时执行,不会产生并发问题,这就是redis的单线程基本模型。
在redis启动初始化的时候,redis会将连接应答处理器和跟AE_READABLE事件关联起来。
当有一个client和redis发起连接,此时会产生一个AE_READABLE事件,然后又对应的事件处理器处理。这个命令处理器就会从socket中读取相关的数据,然后进行执行和处理。
当客户端像redis发起请求的时候(不管是读还是写请求都一样),首先会在socket产生一个AE_READABLE事件,然后由对应的命令请求处理器来处理。这个命令请求处理器就会从socket中读取相应的数据,然后进行执行和处理。
接着redis准备好了给客户端的相应数据之后,就会将socket的AE_WRITABLE ;
事件跟命令回复关联起来,当客户端这边准备好读取响应数据的时候,就会在socket上产生一个AE_WRITABLE事件,会由对应的命令回复处理器来处理,就是将准备好的数据写入socket,共客户端来读取。命令回复处理器写完之后,就会删除这个socket的AE_WRITABLE事件和命令回复处理器的关联关系。
来源:oschina
链接:https://my.oschina.net/u/3126880/blog/4355312