基于LRU-K算法设计本地缓存实现流量削峰

1、背景介绍

1.1、现象

QPS突然增长2倍以上(45w~60w每分钟) 生下面一些问题

1)响应接口响应时长增加了5(qps增加了2)

2机房局域网交换机带宽报警(1kM带宽使用了900M)

3redis获取数据接口响应时长增加等

1.2、原因

1某业务线对有限的产品进行推广

2在短时间内有大量重复数据查询请求

3)短时间从redis获取大量数据

1.3、解决方案

大量请求获取同一份数据,在本地存储这些数据

其优点如下:

1)直接从内存取数据,降低响应时间;

2不走redis减少服务与redis之间的交互流量

3)最终实现流量削峰

2、LRU-K模型设计

2.1、LRU算法介绍

Least recently used(LRU最近最少使用)根据数据的历史访问记录淘汰数据

核心思想

如果数据最近被访问过,那么将来被访问的几率更高

命中率

当存在热点数据时,LRU的效率很好,但偶发性的、周期性的批量操作会导致LRU命中急剧下降,缓存污染情况比较严重。

LRU算法模型如下图:

1)新数据插入到链表头部;

2)每当缓存命中(即缓存数据被访问),则将数据移到链表头部;

3)当链表满的时候,将链表尾部的数据丢弃。

2.2、LRU-K算法设计

LRU-K中的K代表最近使用的次数

主要目的

解决LRU算法“缓存污染”的问题。

核心思想

“最近使用过1次”的判断标准扩展为“最近使用过K次”

命中率

LRU-K降低了“缓存污染”带来的问题,命中率比LRU要高

LRU-K模型如下图:

1)数据第一次被访问,加入到访问历史记录表(简称记录表);在记录表中对应的K单元中设置最后访问时间=new(),且设置访问次数为1;

2)如果数据访问次数没有达到K次,则访问次数+1。最后访问时间与当前时间间隔超过预设的值(如30秒),访问次数清0并加1;

3)当数据访问计数超过(>=)K次后,则访问次数+1。将数据保存到LRU缓存队列中,缓存队列重新按照时间排序;

4)LRU缓存队列中数据被再次访问后,重新排序;

5)LRU缓存队列需要淘汰数据时,淘汰缓存队列中排在末尾的数据,即:淘汰“倒数第K次访问离现在最久”的数据。

子模块LRU存储模型:

类似ConcurrentHashMap,大致由二维数组+链表+访问队列三部分组成

 

Segment数组每个节点包含访问队列,访问队列模型如下图:

Segment数组每个节点都包含一个访问队列,通过这个队列来实现lru算法;

访问队列是一个环状双向链表,LRU算法由访问队列实现

3、缓存框架

3.1、系统数据存储组成

数据存储使用DB+本地缓存(LocalCache)+Redis三层结构,如下图:

3.2、数据查询流程

先从本地缓存取,本地缓存没有从redis取(同时更新本地缓存),redis没有从DB取(同时更新Redis)。具体步骤如下图:

1)先计算该数据获取总次数

2)未达到K访问记录时直接从redis取数据

3)达到K次访问记录时,从本地缓存取,本地缓存不存在时从redis获取数据(同时放入本地缓存中)

3.3、数据更新流程

删除缓存数据后,会再次从redis获取并更新缓存

4、调优过程

4.1、参数动态配置

配置参数如果放在Java类或配置文件中,每次调整都需要重启服务,执行不方便。

配置参数包括 K次访问统计数据清0时长(5分钟->30)K次访问阀值参数、调优日志开关(调优时打开,平时关闭)、本地缓存最大数量等等。

动态调整+实时生效:配置参数放在可实时更新的组件中(如apollo),每次修改后会立即生效。

4.2、性能调优

4.2.1、多机器本地缓存同步增加原来的业务响应时长

优化方案:同步缓存操作改成异步

4.2.2、服务发布时接口抖动

优化方案:

1)服务启动时执行比较耗时初始化操作:如jdbc初始化,K次统计结构初始化。

2)模拟核心dubbo接口,提前生成本地机器码。

5、实际效果

5.1、效果(1)

1)优化参数前QPS增长时,响应时间未见明显变短。如左右第1

2)参数调优上线后。QPS明显增加后,redis请求响应时间增加的情况下,整体响应时间未见变化。见左右最后1

5.2、效果(2)

QPS增加4倍,响应时间未见变化,跟平时一样

demo源代码见:https://download.csdn.net/download/love254443233/10672814

参考方法:LrukCacheTest

参考:

1)缓存淘汰算法--LRU算法

2)LRU算法四种实现方式介绍

3)Java实现的高效计数器

4)Efficient Counter in Java

5)基数排序

6)Guava Cache的缓存管理与使用

7)[Google Guava] 3-缓存

8)guava Cache源码分析(二)

9)Guava Cache内存缓存使用实践-定时异步刷新及简单抽象封装

10)https://gitee.com/liuyaohua/guava

沟通交流请关注公众号。

猜你喜欢

转载自blog.csdn.net/love254443233/article/details/82598381