Redis-总结 (2)

client会一直阻塞到read系统调用返回,也即server返回了数据并且client将数据从内核空间拷贝到了用户空间,这也是传统的BIO采用的方式,这时需要每个socket都对应一个线程

非阻塞

client发出read调用后不会阻塞

由于不会阻塞,此时有两种解决方式

轮询

client周期性的发起read请求,检查是否有server传来的数据已经准备好

IO多路复用

select

建立一个数组包含所有要监听的socket,构建为一个待查队列,当用户进程调用select()时会一直阻塞,直到其中一个socket就绪,同时返回活跃的socket数量,但是不知道具体哪些socket,用户进程需要遍历所有的socket才可以找到哪些socket活跃

poll

类似于select,采用链表方式构建待查队列

epoll

将需要监听的socket和其要执行的事件(如accept)与一个回调函数一并注册到epoll中,构成一个待查队列,其中的事件都还未得到响应;当待查队列上的某个事件激活时,会调用回调函数将此socket和对应事件插入到就绪队列中,那么用户进程每次在调用epoll_wait(类似于select())时,只遍历就绪队列即可,这样省去了检查整个待查队列的开销

NIO-selector

NIO中的selector即Reactor模式中的多路选择(解复用)器,用户进程需要将socket(channel)和对应的事件注册到selector上,之后selector所在线程调用select(),其会阻塞到注册的事件中至少有一个被激活,当select()返回之后调用selectedKeys()用于返回所有的就绪事件对应的key,之后用户进程只需要遍历返回的就绪时间队列,判断对应的事件类型,执行对应的方法即可(如read返回,则开始读数据)

当read系统调用返回后,如果

同步

那么client会一直阻塞等待接收server传来的数据,直到没有数据要传递

异步

那么client会为此事件保留一个callback,不会发生阻塞,当server传来的数据抵达client时,调用callback通知client来开始读取传来的数据

redis中,采用类似于selector的方式,构建了多路复用器,也即前面图中的文件事件分派器,从而避免阻塞等待请求系统调用响应

2.6 失效 2.6.1 缓存穿透

要访问的数据不在redis中时,就会到mysql中去获取,若有人恶意捏造不存在的数据请求,则会为mysql带来巨大压力,因而需要对传来的请求进行数据校验,保证其合法性

至于参数校验可以参考JavaGuide-布隆过滤器

2.6.2 缓存雪崩

redis中的数据大面积失效,这时大量的请求导向mysql,为mysql带来巨大压力,这时可以采用

提高可靠性

主从复制,或者集群多点备份数据

降流

采用消息队列缓存请求,避免冲击mysql

2.7 与memcached对比

主要有如下几点

memcached的value只支持string

memcached不能持久化

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyyjj.html