Java秒杀系统-5.4商品详情页面静态化

 1.为什么要先更新数据库?

先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。然而,这个是逻辑是错误的。试想,两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了。

我不知道为什么这么多人用的都是这个逻辑,当我在微博上发了这个贴以后,我发现好些人给了好多非常复杂和诡异的方案,所以,我想写这篇文章说一下几个缓存更新的Design Pattern(让我们多一些套路吧)。

这里,我们先不讨论更新缓存和更新数据这两个事是一个事务的事,或是会有失败的可能,我们先假设更新数据库和更新缓存都可以成功的情况(我们先把成功的代码逻辑先写对)。

更新缓存的的Design Pattern有四种:Cache aside, Read through, Write through, Write behind caching,我们下面一一来看一下这四种Pattern。

 

Cache Aside Pattern

这是最常用最常用的pattern了。其具体逻辑如下:

失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。

命中:应用程序从cache中取数据,取到后返回。

更新:先把数据存到数据库中,成功后,再让缓存失效。

640?wx_fmt=png

640?wx_fmt=png

注意,我们的更新是先更新数据库,成功后,让缓存失效。那么,这种方式是否可以没有文章前面提到过的那个问题呢?我们可以脑补一下。

一个是查询操作,一个是更新操作的并发,首先,没有了删除cache数据的操作了,而是先更新了数据库中的数据,此时,缓存依然有效,所以,并发的查询操作拿的是没有更新的数据,但是,更新操作马上让缓存的失效了,后续的查询操作再把数据从数据库中拉出来。而不会像文章开头的那个逻辑产生的问题,后续的查询操作一直都在取老的数据。
————————————————
版权声明:本文为CSDN博主「ttu1evldelfq5btqik」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tTU1EvLDeLFq5btqiK/article/details/78693323

 

2.实现:

@Service
public class MiaoshaUserServiceImpl  implements MiaoshaUserService {
    public static final String COOKI_NAME_TOKEN = "token";
    private   static Logger logger= LoggerFactory.getLogger(MiaoshaUserServiceImpl.class) ;
    @Autowired
    private MiaoshaUserDao   miaoshaUserDao;
    @Autowired
    private RedisService   redisService;
    @Override
    public MiaoshaUser getMiaoshaUserById(Long id,String token) {

        MiaoshaUser miaoshaUser = redisService.get(UserKey.getById, token, MiaoshaUser.class);
        if(miaoshaUser!=null){
            return   miaoshaUser;
        }

        MiaoshaUser user = miaoshaUserDao.getById(id);
        boolean set = redisService.set(UserKey.getById, token, user);
        if(!set){
            throw   new GlobalException(CodeMsg.GETBYID_ERROR);
        }
        return user;
    }
    // http://blog.csdn.net/tTU1EvLDeLFq5btqiK/article/details/78693323

    public   boolean   updateUserPassword(String token, long id, String formPass){

        MiaoshaUser user = getMiaoshaUserById(id, token);
        if(user==null){

            throw   new  GlobalException(CodeMsg.USER_PASSWRPD_ERROR);
        }

        //更新数据库
        MiaoshaUser toBeUpdate = new MiaoshaUser();
        toBeUpdate.setId(id);
        toBeUpdate.setPassword(MD5Util.formPassToDBPass(formPass, user.getSalt()));
         miaoshaUserDao.update(toBeUpdate);
        //处理缓存
        boolean delete = redisService.delete(MiaoshaUserKey.token, ""+id);
        redisService.set(MiaoshaUserKey.token,token,user);
        return  true;


    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值