• 展开微博窗口
  • QQ:52619941
  • 微信:cnmemory
  • 展开分类目录
  • 还没有账号?

Memory

一次redis慢的问题分析及解决过程

背景

前段时间,公司某业务在高并发下,单机单个redis实例中,有个大字符串的get操作总是很慢。查看slowlog并无慢日志记录。

原因

通过咨询掌阅@老钱,得到了以下答复

redis的网络读写和逻辑处理都是单个线程处理的,slowlog只是衡量逻辑处理的时间并不包括接受指令和发送响应的时间。字符串的get操作逻辑非常快,所以slowlog没有任何信息。但是网络读写就慢了,特别是高并发下,内存中有大量待发送的缓冲数据堆积在那里,单线程需要拼命地发送数据,所以才会这样缓慢。

解决方案

当时考虑了两种解决方案:

  1. redis集群
  2. 将value进行本地缓存

考虑到项目初期的架构及业务代码的改动量,决定选择第二种方式解决,那么由于项目架构采用的是传统的nginx+php-fpm,无法常驻内存,于是决定利用/dev/shm(tmpfs)将这个value缓存到本地内存文件系统中。

既然用到了本地缓存,就要考虑集群下机器的value一致性,所以最终使用redis在每台机器上部署了一个订阅服务,当value发生改变时,更新本地缓存。

效果

从zabbix中可以很明显看到网络传输的峰值下降了非常多,可见这个key在业务高峰期时读取有多频繁。

结论

对于大字符串,偶尔读写不会存在问题,但是在频繁读写就会给redis带来不小的压力。…

布隆过滤器的原理

布隆过滤器是一种空间利用率高,可以用来对数据进行排重过滤处理的数据结构,具有以下两点特征:

  • 判定为不存在的数据一定不存在
  • 判定为存在的数据可能存在也可能不存在

存在的数据如果实际上并不存在,称为false positive,那么为什么会有这种现象呢?

布隆过滤器是通过k个hash函数将某个key映射到m个的比特位上。那么某个key的比特位有可能会被其他的一个或多个key占用,即会产生误判为存在的情况,所以这个误判率取决于k(hash函数个数)、m(比特位个数)、n(元素个数),关于误差率推导,由于我的数学比较不好,还没领悟透彻,可以参考网络上其他文章。

因为比特位非0既1,且多个key共享比特位,也导致了布隆过滤器无法删除已添加的元素,因为删除某个key会影响到其他key。

当然还有一些其他变种的布隆过滤器使得可以删除元素,例如将比特位变成一个计数器,删除元素时只需要将计数器-1即可。…