引言

讲了几天的数据库系列的文章,大家一定看烦了,其实还没讲完。。。(以下省略一万字)。

今天我们换换口味,来写redis方面的内容,谈谈热key问题如何解决。

其实热key问题说来也很简单,就是瞬间有几十万的请求去访问redis上某个固定的key,从而压垮缓存服务的情情况。

其实生活中也是有不少这样的例子。比如XX明星结婚。那么关于XX明星的Key就会瞬间增大,就会出现热数据问题。

ps:hot key和big key问题,大家一定要有所了解。

本文预计分为如下几个部分

  • 热key问题
  • 如何发现
  • 业内方案

正文

热Key问题

上面提到,所谓热key问题就是,突然有几十万的请求去访问redis上的某个特定key。那么,这样会造成流量过于集中,达到物理网卡上限,从而导致这台redis的服务器宕机。

那接下来这个key的请求,就会直接怼到你的数据库上,导致你的服务不可用。

怎么发现热key

方法一:凭借业务经验,进行预估哪些是热key

其实这个方法还是挺有可行性的。比如某商品在做秒杀,那这个商品的key就可以判断出是热key。缺点很明显,并非所有业务都能预估出哪些key是热key。

方法二:在客户端进行收集

这个方式就是在操作redis之前,加入一行代码进行数据统计。那么这个数据统计的方式有很多种,也可以是给外部的通讯系统发送一个通知信息。缺点就是对客户端代码造成入侵。

方法三:在Proxy层做收集

有些集群架构是下面这样的,Proxy可以是Twemproxy,是统一的入口。可以在Proxy层做收集上报,但是缺点很明显,并非所有的redis集群架构都有proxy。



方法四:用redis自带命令

(1)monitor命令,该命令可以实时抓取出redis服务器接收到的命令,然后写代码统计出热key是啥。当然,也有现成的分析工具可以给你使用,比如redis-faina。但是该命令在高并发的条件下,有内存增暴增的隐患,还会降低redis的性能。

(2)hotkeys参数,redis 4.0.3提供了redis-cli的热点key发现功能,执行redis-cli时加上–hotkeys选项即可。但是该参数在执行的时候,如果key比较多,执行起来比较慢。

方法五:自己抓包评估

Redis客户端使用TCP协议与服务端进行交互,通信协议采用的是RESP。自己写程序监听端口,按照RESP协议规则解析数据,进行分析。缺点就是开发成本高,维护困难,有丢包可能性。

以上五种方案,各有优缺点。根据自己业务场景进行抉择即可。那么发现热key后,如何解决呢?

如何解决

目前业内的方案有两种

(1)利用二级缓存

比如利用ehcache,或者一个HashMap都可以。在你发现热key以后,把热key加载到系统的JVM中。

针对这种热key请求,会直接从jvm中取,而不会走到redis层。

假设此时有十万个针对同一个key的请求过来,如果没有本地缓存,这十万个请求就直接怼到同一台redis上了。

现在假设,你的应用层有50台机器,OK,你也有jvm缓存了。这十万个请求平均分散开来,每个机器有2000个请求,会从JVM中取到value值,然后返回数据。避免了十万个请求怼到同一台redis上的情形。

(2)备份热key

这个方案也很简单。不要让key走到同一台redis上不就行了。我们把这个key,在多个redis上都存一份不就好了。接下来,有热key请求进来的时候,我们就在有备份的redis上随机选取一台,进行访问取值,返回数据。

假设redis的集群数量为N,步骤如下图所示



注:不一定是2N,你想取3N,4N都可以,看要求。

伪代码如下

const M = N * 2
//生成随机数
random = GenRandom(0, M)
//构造备份新key
bakHotKey = hotKey + “_” + random
data = redis.GET(bakHotKey)
if data == NULL {
data = GetFromDB()
redis.SET(bakHotKey, expireTime + GenRandom(0,5))
}

业内方案

OK,其实看完上面的内容,大家可能会有一个疑问。

烟哥,有办法在项目运行过程中,自动发现热key,然后程序自动处理么?

嗯,好问题,那我们来讲讲业内怎么做的。其实只有两步

(1)监控热key

(2)通知系统做处理

正巧,前几天有赞出了一篇《有赞透明多级缓存解决方案(TMC)》,里头也有提到热点key问题,我们刚好借此说明

(1)监控热key

在监控热key方面,有赞用的是方式二:在客户端进行收集

在《有赞透明多级缓存解决方案(TMC)》中有一句话提到

TMC 对原生jedis包的JedisPool和Jedis类做了改造,在JedisPool初始化过程中集成TMC“热点发现”+“本地缓存”功能Hermes-SDK包的初始化逻辑。

也就说人家改写了jedis原生的jar包,加入了Hermes-SDK包。

那Hermes-SDK包用来干嘛?

OK,就是做热点发现本地缓存

从监控的角度看,该包对于Jedis-Client的每次key值访问请求,Hermes-SDK 都会通过其通信模块将key访问事件异步上报给Hermes服务端集群,以便其根据上报数据进行“热点探测”。

当然,这只是其中一种方式,有的公司在监控方面用的是方式五:自己抓包评估

具体是这么做的,先利用flink搭建一套流式计算系统。然后自己写一个抓包程序抓redis监听端口的数据,抓到数据后往kafka里丢。

接下来,流式计算系统消费kafka里的数据,进行数据统计即可,也能达到监控热key的目的。

(2)通知系统做处理

在这个角度,有赞用的是上面的解决方案一:利用二级缓存进行处理。

有赞在监控到热key后,Hermes服务端集群会通过各种手段通知各业务系统里的Hermes-SDK,告诉他们:"老弟,这个key是热key,记得做本地缓存。"

于是Hermes-SDK就会将该key缓存在本地,对于后面的请求。Hermes-SDK发现这个是一个热key,直接从本地中拿,而不会去访问集群。

除了这种通知方式以外。我们也可以这么做,比如你的流式计算系统监控到热key了,往zookeeper里头的某个节点里写。然后你的业务系统监听该节点,发现节点数据变化了,就代表发现热key。最后往本地缓存里写,也是可以的。

通知方式各种各样,大家可以自由发挥。本文只是提供一个思路。

总结

希望通过本文,大家明白如何处理生产上遇到的热key问题。

【原创】谈谈redis的热key问题如何解决的更多相关文章

  1. 谈谈redis的热key问题如何解决

    引言 讲了几天的数据库系列的文章,大家一定看烦了,其实还没讲完...(以下省略一万字).今天我们换换口味,来写redis方面的内容,谈谈热key问题如何解决.其实热key问题说来也很简单,就是瞬间有几 ...

  2. BAT经典面试题之redis的热KEY问题怎么解决

    引言 讲了几天的数据库系列的文章,大家一定看烦了,其实还没讲完...(以下省略一万字).今天我们换换口味,来写redis方面的内容,谈谈热key问题如何解决.其实热key问题说来也很简单,就是瞬间有几 ...

  3. 如何快速定位 Redis 热 key?

    背景 在 Redis 中,热 key 指的是那些在一段时间内访问频次比较高的键值,具体到业务上,商品的限时抢购.瞬时的新闻热点或某个全局性的资源,都极有可能产生热点 key. 热点 key 的出现可能 ...

  4. 京东热 key 探测框架新版发布,单机 QPS 可达 35 万

    https://mp.weixin.qq.com/s/3URAvUF6zwxeF5Kkc1aWHA 京东热 key 探测框架新版发布,单机 QPS 可达 35 万 原创 Hollis Hollis 2 ...

  5. 谈谈Redis的SETNX

    谈谈Redis的SETNX 发表于2015-09-14 在 Redis 里,所谓 SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果,不 ...

  6. 高并发架构系列:Redis并发竞争key的解决方案详解

    https://blog.csdn.net/ChenRui_yz/article/details/85096418 https://blog.csdn.net/ChenRui_yz/article/l ...

  7. Redis系列之key操作命令与Redis中的事务详解(六)

    序言 本篇主要目的有二: 1.展示所有数据类型中key的所有操作命令,以供大家学习,查阅,更深入的挖掘redis潜力. 2.掌握redis中的事务,让你的数据完整性一致性拥有更优的保障. redis命 ...

  8. 单点登录filter根据redis中的key判断是否退出

    package com.ailk.biapp.ci.localization.cntv.filter; import java.io.IOException; import java.util.Has ...

  9. 如何解决Redis中的key过期问题

    最近我们在Redis集群中发现了一个有趣的问题.在花费大量时间进行调试和测试后,通过更改key过期,我们可以将某些集群中的Redis内存使用量减少25%. Twitter内部运行着多个缓存服务.其中一 ...

随机推荐

  1. Hibernate学习---第十五节:hibernate二级缓存

    1.二级缓存所需要的 jar 包 这三个 jar 包实在 hibernate 解压缩文件夹的 lib\optional\ehcache 目录下 2.配置 ehcache.xml <ehcache ...

  2. Javascript-- jQuery事件篇(3)

    on()的多事件绑定 之前学的鼠标事件,表单事件与键盘事件都有个特点,就是直接给元素绑定一个处理函数,所有这类事件都是属于快捷处理.翻开源码其实可以看到,所有的快捷事件在底层的处理都是通过一个&quo ...

  3. codeforces 632A A. Grandma Laura and Apples(暴力)

    A. Grandma Laura and Apples time limit per test 1 second memory limit per test 256 megabytes input s ...

  4. 用nginx搭建http/rtmp/hls协议的MP4/FLV流媒体服务器

    前前后后搭建了两三个星期,终于可以告一段落,nginx实在是有点强大.写一篇笔记来记录一下这个过程中的思路和解决方案. 一.搭建nginx平台: 基本是基于http://blog.csdn.net/x ...

  5. Mysql备份脚本python编写

    #!/usr/bin/env python #-*- coding: UTF-8 -*- ####################################################### ...

  6. 图形化升级单机oracle 11.2.0.4 到 12.2.0.1

    1. 讲补丁包上传到 Oracle server ,解压.安装 [oracle@11g tmp]$ unzip linuxx64_12201_database.zip 2. 检查当前版本 SQL> ...

  7. 非系统数据文件损坏,rman备份恢复

    实验前提:已经做好备份. SQL> col file_name for a50select file_id,file_name from dba_data_files; FILE_ID FILE ...

  8. 桥接以及Mercury MW54R中继

    家里连个路由器,一个是比较先进的TP-Link的TL-WR842N(100M),另外一个是比较古老的水星(Mercury) MW54R(54M),我们知道新的路由器都有WDS功能,方便作为副路由器(中 ...

  9. Impala的JDBC无法连接

    这是因为客户端连接的JDBC是Impala的master机器,而不是DataNode:因为JDBC的服务宿主是Impalad,而Impalad只是部署在DataNode

  10. 一个Web结合Mybatis项目

    需要引入apache.commons.dbcp-1.2.2.osgi.jar以及org.apache.commons.pool-1.5.3.jar用来提供JDBC的访问: 需要org.springfr ...