博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
两级缓存实现分析之缓存设置
阅读量:5782 次
发布时间:2019-06-18

本文共 2691 字,大约阅读时间需要 8 分钟。


title: 两级缓存实现分析之缓存设置 tags:

  • J2Cache
  • 缓存
  • 雪崩
  • 缓存击穿
  • 缓存失效 categories: 工作日志 date: 2017-06-25 18:18:54

上篇描述了缓存过期的代码

本次讨论一下两级缓存如何获取缓存设置,移除,获取

正如文章描述缓存读取顺序

读取顺序  -> L1 -> L2 -> DB复制代码

先描述一下缓存读取代码:

/**     * 获取缓存中的数据     *     * @param region : Cache Region name     * @param key    : Cache key     * @return cache object     */    public CacheObject get(String region, Object key) {        CacheObject obj = new CacheObject();        obj.setRegion(region);        obj.setKey(key);        if (region != null && key != null) {            obj.setValue(CacheManager.get(LEVEL_1, region, key));            if (obj.getValue() == null) {                obj.setValue(CacheManager.get(LEVEL_2, region, key));                if (obj.getValue() != null) {                    obj.setLevel(LEVEL_2);                    CacheManager.set(LEVEL_1, region, key, obj.getValue());                }            } else                obj.setLevel(LEVEL_1);        }        return obj;    }复制代码

首先在localcache中查询,如果可以获得缓存直接返回,

如果不能则去remotecache获取如果可以获得缓存 将localcache设置缓存后直接返回,

如果不能则返回空(CacheObject中的value为null)===》可以实现更多级缓存

这边隐含一个条件(高一级缓存必定拥有比第一级缓存更多并且准确的数据)

此处存在一个缓存击穿的问题:

我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直直接查询然后再缓存查询结果返回。这个时候如果我们查询的某一个数据在缓存中一直不存在,就会造成每一次请求都查询DB,这样缓存就失去了意义,在流量大时,可能DB就挂掉了。

无论多级缓存都存在此问题,对于此处的解决方案建议对使用缓存的返回结果包装(Optional)可以使用google或者java8的可选对象,如果db查询或者计算结果为空,显示的返回Absent对象,可以避免大量无效的key导致的缓存击穿问题

下面介绍缓存的设置实现

public void set(String region, Object key, Object value, Integer expireInSec) {        if (region != null && key != null) {            if (value == null)                evict(region, key);            else {                // 分几种情况                // Object obj1 = CacheManager.get(LEVEL_1, region, key);                // Object obj2 = CacheManager.get(LEVEL_2, region, key);                // 1. L1 和 L2 都没有                // 2. L1 有 L2 没有(这种情况不存在,除非是写 L2 的时候失败                // 3. L1 没有,L2 有                // 4. L1 和 L2 都有                _sendEvictCmd(region, key);// 清除原有的一级缓存的内容                CacheManager.set(LEVEL_1, region, key, value, expireInSec);                CacheManager.set(LEVEL_2, region, key, value, expireInSec);            }        }        // log.info("write data to cache region="+region+",key="+key+",value="+value);    }复制代码

正如上文所述,高级缓存(L2)必然承载更多低级缓存所不存在的数据

首先发起命令清除所有一级缓存的对应key(保证其他一级缓存的值已被清除,不会出现缓存不一致)

分别在各级缓存设置对应的key和value

对于db或者其他计算资源来说如果过载会发生较为严重的后果,比如无返回,超时甚至宕机。

缓存雪崩就是可能出现的原因之一。

如果出现某个缓存在一段时间后过期了,同时出现高并发获取该缓存将会出现缓存雪崩,

首先查询该缓存发现不存在后立刻去向db获取数据,该处可能将一瞬间的流量完全打到db上

导致db负债过高使得应用超时乃至宕机

通常解决方案只能通过getCache时如果key不存在就增加一把锁,使得其他线程必须等待到锁释放

当然还有缓存失效问题

用户在初次使用系统时,可能要针对该用户存储大量缓存,设想场景均为24h,那么当24h后所有缓存过期

同样可能出现大量流量打到db出现异常。

通常解决方案是在过期时间上加上一定长度的随机数,使得缓存不至于一刹那全部过期导致db流量过大

转载地址:http://hdjyx.baihongyu.com/

你可能感兴趣的文章
Mysql读写分离
查看>>
Oracle 备份与恢复学习笔记(5_1)
查看>>
Oracle 备份与恢复学习笔记(14)
查看>>
分布式配置中心disconf第一部(基本介绍)
查看>>
Scenario 9-Shared Uplink Set with Active/Active uplink,802.3ad(LACP)-Flex-10
查看>>
UML类图中的六种关系
查看>>
探寻Interpolator源码,自定义插值器
查看>>
一致性哈希
查看>>
mysql(待整理)
查看>>
2012年电信业八大发展趋势
查看>>
Web日志安全分析工具 v2.0发布
查看>>
JS重载
查看>>
python2和python3同安装在Windows上,切换问题
查看>>
php加速工具xcache的安装与使用(基于LNMP环境)
查看>>
android超链接
查看>>
redhat tomcat
查看>>
统计数据库大小
查看>>
IO流的学习--文件夹下文件的复制
查看>>
第十六章:脚本化HTTP
查看>>
EXCEL表中如何让数值变成万元或亿元
查看>>