Memcached为什么比Redis更能抗热点
Memcached为什么比Redis更能抗热点
热点问题的本质
热点 key 最主要的问题还是它会导致缓存的流量不均衡,会导致单节点流量过高,无法发挥集群的作用,整个Redis集群能支撑的QPS就退化成了单个实例能支撑的QPS了
Memcached 为什么抗热点性能更好
第一个是 Memcached 通过多线程可以利用多核,从而可以显著提升单个实例的吞吐,针对这种流量倾斜的情况可以更好的应对
下图是一个例子,假设每个CPU核能支撑5W QPS(不考虑其他的开销,比如多线程的开销,实现的不同),Memcached和Redis从集群维度都可以抗10W QPS,但是具体到热点请求,单个Redis实例就只能抗5W QPS了,这样两者的抗热点能力就差了一倍,线上我们的Memcached实例通常会开10个线程或者更多,Memcached和Redis单实例的吞吐能力会有更大的差异
如果我们的机器只有1核,对于get/set的操作Memcached的抗热点能力可能还不如Redis,因为多线程还会有一些部分额外的开销
第二个是Redis的一些数据结构的操作复杂度并不是O(1),比如zrange,复杂度是O(log(N) + M),如果对于有1000(对应N)个元素的zset取100(对应M)个,那它的开销肯定要远大于get,对于这些操作单个redis实例能支撑QPS会降低很多,那相应的抗热点能力也会更差
Memcached 一定能抗热点吗
绝大部分场景下Memcached抗热点能力还是能达到预期效果的,但是如果你的Key比较大,那这个结论就可能不成立了,对于大Key 它的瓶颈可能不在CPU而是在网卡的带宽上了
对于一些大Key的访问,可能几万QPS就能把网卡的带宽用满了,而且这个最坑的地方是,如果单个Memcached实例把网卡占满了,部署在这台机器上的其他实例也会受影响,所以我们尽量还是要避免一些大Key的情况,如果Key比较大那Memcached的抗热点能力也会显著下降
热点处理方案
本地缓存
通过 LoadingCache
将数据暂存到主调内存中,可以有效降低对缓存的压力
本地缓存对于的get/set的操作实现比较简单,但是对于zrange这些涉及多个参数命令会麻烦一些,除了Key还需要传入一些其他的参数,比如from,limit等,如果将这些参数作为本地缓存的key,那可能出现参数变化本地缓存key失效的情况,比如有个zset使用时间作为score,我们需要按照时间倒序取前100个元素,如果from用Double.MAX_VALUE没什么问题,但是如果from使用的是System.currentTimeMillis,那每次请求参数都会变化,本地缓存就失效了