zoukankan      html  css  js  c++  java
  • 同时使用Redis缓存和Google Guava本地缓存注意事项(深拷贝和浅拷贝)

    1、问题场景及说明

    系统中同时使用 Redis 缓存和 Guava本地缓存。用 Guava 缓存将 Redis 缓存包了一层。可以提升效率,但是也会引出一些问题。

    问题:同一个本地缓存Map,获取到的值有时会不一致。
    不同机器可能不一致,同一机器也可能不一致。很神奇,但是数据库里都是对的。

    后来发现,因为有一个请求会对该缓存进行remove操作,导致缓存改变。
    如果这个请求到某个机器上,该台机器上的缓存就会被修改。
    同时缓存过期时间为一分钟,过期之后获取到的缓存是正常的。如果该台机器没有再次接收到请求,那么缓存就正常;如果再次接收到,缓存就异常了。

    2、Redis 缓存是深拷贝

    从 Redis 中获取缓存时,系统中的数据对象是 Redis 缓存的副本。
    对该对象的任何操作都不会影响 Redis 中的缓存,后续再次获取还是修改之前的数据。
    除非执行Redis的更新操作。

    3、Guava本地缓存直接获取则是浅拷贝

    以获取一个MAP为例:如果直接从缓存中取,则是浅拷贝。
    对缓存数据的任何操作都会同时修改缓存中的数据,下次从缓存中获取则是修改之后的数据。

    一般不会修改从缓存中获取到的数据,但如果要修改,则需注意Redis和Guava的不同。

    4、如何实现Guava获取本地缓存是深拷贝?

    方法:可将Guava的get方法封装一层,将缓存中获取到的数据包装为一个新对象返回,以后直接使用封装后的方法。

    注意:这会影响Guava的性能,毕竟每次都需要构建一个新对象返回。

    建议:本地缓存适合直接获取的场景,没必要包装通用get方法。
    如果要修改获取到的数据,在修改的地方深拷贝一份操作即可。
    即可利用Guava的优越性,又可实现需要修改数据的逻辑。
    只是要注意,修改时不能直接操作原始对象,需操作深拷贝之后的对象。

  • 相关阅读:
    数据结构一
    MVC5.0(一)
    异步多线程(六)lock锁
    异步多线程(五)多线程异常处理
    异步多线程(四)Task
    paypal payflow设置视频教程
    Java栈Stack知识点
    Java知识树梳理
    js定时器
    jdk环境变量配置改变不生效的问题
  • 原文地址:https://www.cnblogs.com/buwuliao/p/11849427.html
Copyright © 2011-2022 走看看