Redis의 단축키 문제를 어떻게 처리하나요? 다음 기사에서는 Redis 캐시 단축키 문제에 대한 일반적인 솔루션을 소개합니다. 도움이 되길 바랍니다.
일부 C 측 비즈니스를 수행할 때 데이터베이스의 부담을 대체하고 비즈니스 응답 시간을 줄이기 위해 1차 캐시를 도입하는 것은 불가피합니다. 실제로 문제를 해결하기 위해 매번 미들웨어가 도입됩니다. , 이는 이전 기사 "실제 데이터베이스 및 캐시 일관성"에서 언급한 캐시 일관성을 달성하는 방법과 같은 많은 새로운 문제를 필연적으로 야기할 것입니다. 실제로 Redis를 1차 캐시로 사용할 때 발생할 수 있는 핫키, 큰 키 등과 같은 다른 문제도 있을 것입니다. 이번 글에서는 핫키 및 <code>단축키
문제를 해결하는 방법. -
热key(hot key)
问题来讨论,如何合理的解决热key
问题。
热key
是什么问题,如何导致的?
一般来说,我们使用的缓存Redis都是多节点的集群版,对某个key进行读写时,会根据该key的hash计算出对应的slot,根据这个slot就能找到与之对应的分片(一个master和多个slave组成的一组redis集群)来存取该K-V。但是在实际应用过程中,对于某些特定业务或者一些特定的时段(比如电商业务的商品秒杀活动),可能会发生大量的请求访问同一个key。所有的请求(且这类请求读写比例非常高)都会落到同一个redis server上,该redis的负载就会严重加剧,此时整个系统增加新redis实例也没有任何用处,因为根据hash算法,同一个key的请求还是会落到同一台新机器上,该机器依然会成为系统瓶颈2,甚至造成整个集群宕掉,若此热点key的value 也比较大,也会造成网卡达到瓶颈,这种问题称为 “热key” 问题。【相关推荐:Redis视频教程】
如下图1、2所示,分别是正常redis cluster集群和使用一层proxy代理的redis 集群key访问。
如上所说,热key会给集群中的少部分节点带来超高的负载压力,如果不正确处理,那么这些节点宕机都有可能,从而会影响整个缓存集群的运作,因此我们必须及时发现热key、解决热key问题。
热key探测,看到由于redis集群的分散性以及热点key带来的一些显著影响,我们可以通过由粗及细的思考流程来做热点key探测的方案。
热key最明显的影响是整个redis集群中的qps并没有那么大的前提下,流量分布在集群中slot不均的问题,那么我们可以最先想到的就是对于每个slot中的流量做监控,上报之后做每个slot的流量对比,就能在热key出现时发现影响到的具体slot。虽然这个监控最为方便,但是粒度过于粗了,仅适用于前期集群监控方案,并不适用于精准探测到热key的场景。
如果我们使用的是图2的redis集群proxy代理模式,由于所有的请求都会先到proxy再到具体的slot节点,那么这个热点key的探测统计就可以放在proxy中做,在proxy中基于时间滑动窗口
,对每个key做计数,然后统计出超出对应阈值的key。为了防止过多冗余的统计,还可以设定一些规则,仅统计对应前缀和类型的key。这种方式需要至少有proxy的代理机制,对于redis架构有要求。
redis 4.0以上的版本支持了每个节点上的基于LFU的热点key发现机制,使用redis-cli –hotkeys
即可,执行redis-cli时加上–hotkeys选项。可以定时在节点中使用该命令来发现对应热点key。
如下所示,可以看到redis-cli –hotkeys
단축키
어떻게 발생하나요?
시간 슬라이딩 창
을 기반으로 프록시에서 수행될 수 있습니다. 각 키를 계산한 다음 해당 임계값을 초과하는 키를 계산합니다. 너무 많은 중복 통계를 방지하기 위해 접두사 및 유형에 해당하는 키만 계산하도록 일부 규칙을 설정할 수도 있습니다. 이 방법에는 최소한 프록시 메커니즘이 필요하며 Redis 아키텍처에 대한 요구 사항이 있습니다. 🎜redis-cli –hotkeys
를 사용하세요. redis-cli를 실행할 때 –hotkeys 옵션을 추가하세요. 노드에서 정기적으로 이 명령을 사용하여 해당 핫스팟 키를 검색할 수 있습니다. 🎜🎜🎜🎜 as 그림과 같이 redis-cli –hotkeys
의 실행 결과와 단축키에 대한 통계 정보를 확인할 수 있으며, 이 명령의 실행 시간이 길며 예약 실행을 설정할 수 있습니다. 통계를 수집합니다. 🎜Redis 명령은 매번 클라이언트에서 발행되므로 이를 기반으로 Redis 클라이언트의 일부 코드에서 통계 계산을 수행할 수 있으며 각 클라이언트는 시간 슬라이딩 창을 기반으로 통계를 수행합니다. 특정 임계값을 초과하면 서버에 보고되고, 서버는 이를 각 클라이언트에 균일하게 전송하고 해당 만료 시간을 구성합니다.
이 방법은 더 아름다워 보이지만 실제로는 클라이언트 측 수정으로 인해 실행 중인 프로세스에 더 큰 메모리 오버헤드가 발생하기 때문에 일부 애플리케이션 시나리오에서는 그다지 적합하지 않습니다. 더 직접적으로는 다음과 같은 자동 메모리 관리 기능이 있는 언어입니다. Java와 goLang은 객체를 더 자주 생성하여 gc를 트리거하고 인터페이스 응답 시간을 증가시키는 것은 예측하기 쉽지 않습니다. 优美
,其实在一些应用场景中并不是那么合适,因为在client端这一侧的改造,会给运行的进程带来更大的内存开销,更直接的来说,对于Java和goLang这种自动内存管理的语言,会更加频繁的创建对象,从而触发gc导致接口响应耗时增加的问题,这个反而是不太容易预料到的事情。
最终可以通过各个公司的基建,做出对应的选择。
通过上述几种方式我们探测到了对应热key或者热slot,那么我们就要解决对应的热key问题。解决热key也有好几种思路可以参考,我们一个一个捋一下。
一种最简单粗暴的方式,对于特定的slot或者热key做限流,这个方案明显对于业务来说是有损的,所以建议只用在出现线上问题,需要止损的时候进行特定的限流。
本地缓存也是一个最常用的解决方案,既然我们的一级缓存扛不住这么大的压力,就再加一个二级缓存吧。由于每个请求都是由service发出的,这个二级缓存加在service端是再合适不过了,因此可以在服务端每次获取到对应热key时,使用本地缓存存储一份,等本地缓存过期后再重新请求,降低redis集群压力。以java为例,guavaCache就是现成的工具。以下示例:
//本地缓存初始化以及构造 private static LoadingCache<String, List<Object>> configCache = CacheBuilder.newBuilder() .concurrencyLevel(8) //并发读写的级别,建议设置cpu核数 .expireAfterWrite(10, TimeUnit.SECONDS) //写入数据后多久过期 .initialCapacity(10) //初始化cache的容器大小 .maximumSize(10)//cache的容器最大 .recordStats() // build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存 .build(new CacheLoader<String, List<Object>>() { @Override public List<Object> load(String hotKey) throws Exception { } }); //本地缓存获取 Object result = configCache.get(key);
本地缓存对于我们的最大的影响就是数据不一致的问题,我们设置多长的缓存过期时间,就会导致最长有多久的线上数据不一致问题,这个缓存时间需要衡量自身的集群压力以及业务接受的最大不一致时间。
如何既能保证不出现热key问题,又能尽量的保证数据一致性呢?拆key也是一个好的解决方案。
我们在放入缓存时就将对应业务的缓存key拆分成多个不同的key。如下图所示,我们首先在更新缓存的一侧,将key拆成N份,比如一个key名字叫做"good_100",那我们就可以把它拆成四份,"good_100_copy1"、"good_100_copy2"、"good_100_copy3"、"good_100_copy4",每次更新和新增时都需要去改动这N个key,这一步就是拆key。
对于service端来讲,我们就需要想办法尽量将自己访问的流量足够的均匀,如何给自己即将访问的热key上加入后缀。几种办法,根据本机的ip或mac地址做hash,之后的值与拆key的数量做取余,最终决定拼接成什么样的key后缀,从而打到哪台机器上;服务启动时的一个随机数对拆key的数量做取余。
对于熟悉微服务配置中心的伙伴来讲,我们的思路可以向配置中心的一致性转变一下。拿nacos来举例,它是如何做到分布式的配置一致性的,并且相应速度很快?那我们可以将缓存类比配置,这样去做。
长轮询
+本地化
장기 폴링
+현지화
구성. 먼저 서비스가 시작되면 모든 구성이 초기화된 후 정기적으로 롱 폴링이 시작되어 현재 서비스 모니터링 구성이 변경되었는지 확인합니다. 변경 사항이 있는 경우 롱 폴링 요청이 즉시 반환되어 로컬 구성을 업데이트합니다. 변경 사항이 없으면 모든 비즈니스 코드에 대해 로컬 메모리 캐시 구성을 사용합니다. 이는 분산 캐시 구성의 적시성과 일관성을 보장합니다. 🎜위의 각 솔루션은 단축키 문제를 해결하기 위해 상대적으로 독립적이므로 실제로 비즈니스 요구 사항에 직면하면 실제로 전체 솔루션 설계를 고려하는 데 오랜 시간이 걸립니다. . 일부 극단적인 플래시 판매 시나리오로 인해 발생하는 핫키 문제의 경우 예산이 충분하다면 서비스 비즈니스와 Redis 캐시 클러스터를 직접 격리하여 정상적인 비즈니스에 영향을 미치지 않도록 할 수 있으며 동시에 일시적으로 더 나은 재해 복구를 채택할 수 있습니다. 전류 제한 조치.
시장에는 이미 상대적으로 완전한 핫키용 애플리케이션 수준 솔루션이 많이 있습니다. 그중 JD.com에는 이와 관련하여 클라이언트에 대한 통찰력을 제공하는 오픈 소스 핫키 도구가 있습니다. 측에서 응답 핫키를 보고하면 서버가 이를 감지한 후 로컬 캐싱을 위해 해당 핫키를 해당 서버로 보냅니다. 이 로컬 캐시는 원격 해당 키가 업데이트된 후 동시에 업데이트됩니다. 현재 솔루션, 自动探测热key、分布式一致性缓存
JD Retail 단축키.
프로그래밍 소개를 방문하세요! !
위 내용은 Redis에서 캐시 단축키 문제를 처리하는 방법에 대해 이야기해 볼까요? 일반적으로 사용되는 솔루션 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!