• 缓存击穿,双缓存处理策略


    微信公众号:molashaonian

    缓存击穿

    某一个热点 key,在缓存过期的一瞬间,同时有大量的请求打进来,由于此时缓存过期了,所以请求最终都会走到数据库,造成瞬时数据库请求量大、压力骤增,甚至可能打垮数据库。

    场景:商品列表,商品详情展示销量,库存等

    大多解决方案

    • 加互斥锁。在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。

    • 热点数据不过期。直接将缓存设置为不过期,然后由定时任务去异步加载数据,更新缓存。

    缺点:两种方案问题是能解决,但不是很漂亮,会产生阻塞,增加额外处理资源问题

    双缓存处理策略

    对于热点 key 可以设置一级,二级缓存;二级缓存可以设置较长的过期时间(甚至不过期),当一级缓存过期时,加锁从数据库中获取最新值,并且更新一级,二级缓存;同时没获得锁的线程直接读取二级缓存返回。

    请求 一级缓存 二级缓存 MySQL 查询 缓存失效,加锁获取最新值,并且更新一级,二级缓存 查询 缓存失效,获取锁失败,读取二级缓存 更新 更新 请求 一级缓存 二级缓存 MySQL
     

    代码实现

    public List<GoodsRespDTO> findGoodsList() {
        String key = "page:homepage:goods";
    	List<GoodsRespDTO> respDto = myRedis.get(key);
    	if(respDto != null) {
    		return respDto;
    	}
    	// 双缓存机制,加锁更新缓存
        Lock lock = myRedis.getLock(key + ":update");
        if (lock.tryLock(-1, 5000)) {
            try {
            		// 查询数据库逻辑
                    respDto = selectMySQL();
                    if(respDto != null) {
                        // 更新一级缓存
                        myRedis.set(key, respDto, 3000);
                        // 更新二级缓存
                        myRedis.set(key + ":L2Cache", respDto, 8500);
                    }
                    return respDto;
                }
            } finally {
                lock.unLock();
            }
        }
        // 二级缓存
        return myRedis.get(key + ":L2Cache");
    }
    

    微信公众号:molashaonian
    Alt

  • 相关阅读:
    DateTimeHelper
    Check F5 refresh submit post back repeatly
    GZip Compress SoapExtension
    WebBrowser 高级扩展 js扩展 js订阅C#事件
    DataSet GZip/Deflate Serializer
    Socket/Stream Data Helper
    历年评书出版一览表(1955~1994)
    c#检测字节流编码
    Execute SQL Server Store Procedure C# ADO.Net Wrapper Code Generator
    Directory File Disk Searcher
  • 原文地址:https://www.cnblogs.com/molashaonian/p/16229888.html
Copyright © 2020-2023  润新知