粉丝5159获赞2.3万

redist 的 热屁问题你可能一辈子都遇不到,但是在面试中经常会被问到,尤其是高并发的项目,那现在啊,谁还不在自己的简历当中写个三高的项目撑撑场面呢?我爱说实话, 那在高并发的项目中,我们的 redist 通常会集群不足,数据会进行分片,比如平摊到这三个节点中,那在理想的情况下,我们肯定希望请求的流量能够平均地分散到这三个节点, 但是在实际的某些场景可能会事与愿违,比如秒杀,我们就会对某一个热门的商品进行扣减库存,或者在爆火的直播间,我们需要统计观看人数,那这个时候这些访问的 key 都会集中到某一个节点中,那这些 key 我 们就称之为热 key。 当 qps 达到百万级别或者大几十万啊,那这个热 key 所属的节点它就会扛不住,因为 reddit 从理论上面来说,单机最高支持写五万 十万,所以在极端的情况下, cpu 会直接飙到百分之百,网络贷款直接被打满,甚至直接断机,那这个节点下所有的请求,包括其他 t 的 请求都会超时,那一旦热气所属的节点断机了,或者超迟了,那大量的请求呢,就会击穿 radis 打到数据库,那数据库的连接直接会被打满, 导致数据库直接崩溃,甚至整个系统血红。那关于缓存的击穿问题,我们可以采用,比如设置数据永不过期,我们可以等秒杀结束或者下播之后呢,再去清除热点 key, 或者采用分布式锁。在缓存过期之后呢,同一时间之内,只允许有一个请求 去数据库当中查询数据,并且填充 radis, 那 我这里呢,还有关于 radis 甚至 java 所有技术栈的高频面试题,大家需要的话也可以直接拿去。但是热点 key 导致的 radis 断机问题,我们就需要通过其他的解决手段了,比如说热点分散, 这种解决方案呢,是最简单有效的,只需要将我们的库存 key 再进行分片即可。比如说我有一百二十万库存,我给他 分成三个节点,每个节点呢提供四十万库存进行扣减。那关键是我们同一个 key 怎么能够平均的分散到这三个节点呢?那我们可以采用比如 usid 或者 o 的 id 来进行曲模节点的数量,那通过 usid 和 o 的 id, 它的离散性呢?我们就可以让它平均的 行分配访问。但是这种方式呢,他只能应对那些有准备的热点 key, 比如说秒杀,我知道什么时间段会进行秒杀,而不是突发的,所以我就可以在秒杀之前呢对这个商品的库存来进行分享。但是有些场景,比如直播,他因为有些热点直接变成了热门直播间,那你通过热点分享呢,可能就会措手不及。那我们可以通过应用层的 本地缓存,在应用层呢,加一道屏障单请求进来,先去访问本地缓存,如果本地缓存没有呢,再通过分布所,同一个时间只能有一个请求 去请求 radis, 然后把查询到的数据填充到本地缓存。所以通过本地缓存呢,它可以帮我们挡住百分之九十九以上的数据访问,并且你一个应用压力大,我去对这个应用来进行集群就可以了,好吧,所以针对热 key 的 问题呢,我们通常会采用本地缓存加热点分散这两种方案来应对不同的情况。热点分散呢,主要去应对有 准备的热点,替本地缓存的应对突发的热点。当然我们在实际开发当中肯定还需要结合限流垄断降级来有效的保证系统的一个稳定,安全性好。关于热 key 的 问题以及解决方案,我就给大家分享到这里,我们下期见。 那最紧要面试求职换工作的也可看过来啊,我给大家准备一份一百多万字的加班面试宝典,里面基本上囊括了现在 java 的 主流技术上的高频问题,项目是在问现在面的排查,到我这系统去看一看,那包括如果说你也陷围的问题, 线上没有面试机看都可以代查,帮你有面基简历替换案呢,它可以有面试机会,比方没有用哈密斯大 t, 很多人在工作当中并没有遇到过,但是面试经常会被问到,多大算是大 t, 大 t 会有哪些影响,大 t 如何排查,如何安全地删除大 t 呢?以及如何进行预防?还有涉及到的面试题, 我们应该如何进行回答?在这个视频当中呢,给大家详细的进行讲解和本视频配套的笔记资料,以及更多的高频面试题,大家需要的话可以在评论区扣六六六来进行获取。那到底什么是大 t? 多大算是大呢?那很多人认为大 t 嘛,肯定就是 t 很 长 就是大 t, 其实不对啊,你想一下,我们通常在使用 radis 的 时候, t 能有多长呢?我给你一兆去存够你存了吧。所以我们通常衡量大 t 呢,有两个维度的指标,你像 string 类型呢,我们通常是看它的 value 的 体积。 一般来说,超过十兆的 street, 我 们就需要高度的去警惕了,比如说一整篇文章,比如说一个文件,你把它直接塞到 street 里面去,那一次网络的请求就有可能把服务器贷款直接给你打满。那对于 集合类型啊,我们更关注的是它内部元素的数量。通常按照经验来说,成员数量超过了五千个,那它就是一个潜在的大 key 了。比如说一个拥有几百万粉丝的粉丝列表,你对它做一次全量操作,就有可能直接让 read 卡住很久。所以记住啊,大 key 并不是指 t 很 长,而是由 value 的 体积还有集合的成员数量来决定的。它的本质呢,就是会导致一次命令操作的资源开销过大,从而卡住你的 radis。 那 么再来说一下大 k 啊,它有什么影响呢? 你可以把 radis 的 服务器啊,想象成一根水管,当你请求一个几十兆的大 k 的 时候,就相当于呢,把一块巨大的石头塞进了水管,瞬间就把它堵死了。那在这个期间啊,其他所有正常的微小的石头塞进了水管,瞬间就把它堵死了。那在这个期间啊,其他所有正常的石头塞进了水管,瞬间就把它堵死了。那在这个期间啊,其他所有正常的服务响应 极其的缓慢。就是因为 radis 呢,它是单线成的,所以一旦出现了大 key 呢,后面的命令,它都会排队等待,导致命令 堵塞,那另外呢,也会导致集群迁移发生困难。那既然大 key 的 危害这么大,我们怎么在它引爆之前找到它呢?在这里我提供三种侦查手段,那第一个呢,就是通过 radis, 它自带的这个命令 big keys 用起来呢,也非常的简单,只需要在 mini 窗口呢打上这个命令,那它就会对所有的实力呢进行扫描,并且告诉你每种数据类型最大的 key, 比如哈希啊, list 啊, string 啊等等。那更详细的说明呢,在笔记里面都给它列出来了,大家可以自己拿到去看。那另外呢,还有一个叫做 memory use, 那 通过这个命令呢,我们可以查看某一个 key 它占用了多少字节的内存, 更多的用法呢,也在笔记当中给它列出来了,那这个命令呢,它本身在计算这个大 key 的 时候啊,可能会导致堵塞,所以在生产环境当中呢,要慎用。当然最有效的手段呢,是能够建立一个监控和告警的方案,比如说我们可以用 radis, 它自带的 radis insight, 或者用 prometheus 都可以进行监控,一旦超过我们设定的域值呢,就立即进行报警,这样呢能够做到防范于未然。那关键是我们发现了大 key 之后, 怎么删除掉呢?你不可能直接一个 delete 命令啊,那相当于直接引爆了炸弹,会直接堵塞你的 read。 那 针对不同的数据类型呢,我们可以采用不同的手段,比如说 string 类型。那针对 string 类型呢,它的大体其实本身就不应该存在 read 里面。举个例子,就比如说你存的是静态文件,那其实你就可以把这个文件呢 给它迁移到资源服务器里面,在 read 里面呢,只去存它的 u i l, 那 针对哈希和 set, 我 们的核心思想是分批次的删除,比如说我们用 h scan, 每次呢只获取一百个元素,然后用 h d 类把这一百个呢给它删掉,然后再根据返回的油标呢再继续下一轮的删除,直到整个 key 呢被删除掉。那针对 list 呢,我们可以用 ltrim 命令,比如说这个 list 里面它有十万个元素,我们通过 ltrim 呢可以先把前一百个呢给它裁掉,然后呢循环的去执行这个操作,每次温柔地给它 反掉一小部分,直到这个 list 呢为空。那这些温柔的手段呢,其实就是一次地把一些大的耗时的删除操作分解成无数次微小的,快速地删除, 避免长时间的去堵塞 read。 那 我们删除掉大 key 呢?其实也只是亡羊补牢,不能真正的去解决。最有效的方式其实是在设计上直接杜绝掉,就比如说那些集合,我们可以采用分片的策略,把一个大 key 分 散到 几个小 key 里面去,比如说你有五十万粉丝要存到 read 里面,那么我可以根据用户的 id, 然后呢再根据分片键给它分散到十个或者是一百个都可以。那另外呢,就是我们刚刚讲到的 stream 的 大 key, 如果你里面存了一个文件的大的文本,那我们是不是可以把文件给它存储到我们的资源服务器,或者你里面呢存了一些很大的 jason, 那 你是不是也可以采用分片的这个思想,把它切成多个块来进行存储,然后在读取的时候呢,把它们拼起来。那另外呢,我们还可以去设置合理的过期时间,对于那些 可能会长期增长的数据,比如说日期啊,用户的行为记录啊,给它设置一个合理的过期时间,或者通过内存定时的无限堆积,那跟大 k 相关的面试题呢? 还有就是为什么删除大 t 会阻色,那么我们前面也提到了,因为 radis 它是单线成的,就比如说左边这个红色,它是一个巨大的删除大 t 的 任务,那么它一旦执行呢, 就会占用 radis 唯一的工作进程。而它后面的这一长串绿色微小的任务,它们本身执行起来会非常的快,可能只需要几微秒,但是因为前面这个大块头挡住了路,那么它们呢只能在后面焦急地排队等待。这就是组测的本质啊,在删除大 t 的 那几秒钟里面,后续的命令都得干等着,那整个服务器对外看起来呢,就像是卡死了。那我们之前 讲的这种温柔的删除法,也就是分段的删除,其实它的聪明之处就是它把一个大的删除任务拆解成了 n 个微小的删除任务, 每次执行完一个小的删除,就会把现成让出来,让队列后面其他的命令呢有机会执行。那这样呢,虽然总的删除时间可能更长,但是服务在宏观上它是持续可用的,不会出现 长时间的假死现象。那我们最后来总结一下,首先就是对于大 key 的 定义,我们不仅要看歪扭的体积,也要看元素的数量,以及出现了大 key, 它会阻涩后面的命令的执行,以及造成我们 radis 卡顿以及呢迁移会比较困难。那其实 radis 呢,它也提供了一些发现大 key 的 一些命令,那最好的方式呢, 就是建立一个有效的持续监控的手段,这样一旦出现了大 key 呢,我们可以立马进行处理,当然处理的手段并不说直接给它 类,我们应该渐近式的给它拆成小的任务进行删除。当然大 key 呢,最好是能够在设计的时候就能给它防范于未然,比如说我们可以通过分片啊,拆分啊,设置过期时间啊,那么导致大 key 会堵塞的原因其实就是因为 radis, 它是单线的模型。好吧,希望大家能够掌握关于 radis 大 key 这一块的知识点,那我就给大家讲到这里,如果视频对你有帮助,可以给徐老师一键三连,我们下期见。
