前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis实现乐观锁继而实现抢红包功能

Redis实现乐观锁继而实现抢红包功能

作者头像
名字是乱打的
发布2022-05-13 09:00:43
4040
发布2022-05-13 09:00:43
举报
文章被收录于专栏:软件工程

今天去面试了,面试官问了个问题,高并发情况下,怎么防止库存超卖?

回去之后搜了一下解决方法,其中的一种解决方法就是通过给数据库加锁,也可以防止库存超卖的情况

数据的锁定分为两种,第一种叫作悲观锁,第二种叫作乐观锁。

1、悲观锁,就是对数据的冲突采取一种悲观的态度,也就是说假设数据肯定会冲突,所以在数据开始读取的时候就把数据锁定住。【数据锁定:数据将暂时不会得到修改】

2、乐观锁,认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让用户返回错误的信息。让用户决定如何去做。

理解:

    1. 乐观锁是一种思想,具体实现是,表中有一个版本字段,第一次读的时候,获取到这个字段。处理完业务逻辑开始更新的时候,需要再次查看该字段的值是否和第一次的一样。如果一样更新,反之拒绝。 之所以叫乐观,因为这个模式没有从数据库加锁。
  • 2. 悲观锁是读取的时候为后面的更新加锁,之后再来的读操作都会等待。这种是数据库锁 乐观锁优点程序实现,不会存在死锁等问题。他的适用场景也相对乐观。阻止不了除了程序之外的数据库操作。 悲观锁是数据库实现,他阻止一切数据库操作。

再来说更新数据丢失,所有的读锁都是为了保持数据一致性。 乐观锁如果有人在你之前更新了,你的更新应当是被拒绝的,可以让用户从新操作悲观锁则会等待前一个更新完成。这也是区别

具体业务具体分析 实现:

一、悲观锁
代码语言:javascript
复制
    1、排它锁,当事务在操作数据时把这部分数据进行锁定,直到操作完毕后再解锁,
  其他事务操作才可操作该部分数据。这将防止其他进程读取或修改表中的数据。
代码语言:javascript
复制
    2、实现:大多数情况下依靠数据库的锁机制或者JAVA代码中的锁实现

二、乐观锁

代码语言:javascript
复制
    1、如果有人在你之前更新了,你的更新应当是被拒绝的,可以让用户重新操作。
代码语言:javascript
复制
  2、实现:大多数基于数据版本(Version)记录机制实现
 当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加
一。

当我们提交更新的时候,判断当前版本信息与第一次取出来的版本值大小,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据,拒绝更新,让用户重新操作。

乐观锁的具体实现模式:

我们知道大多数是基于数据版本(version)的记录机制实现的。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个”version”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1。此时,将提交数据的版本号与数据库表对应记录的当前版本号进行比对,如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据。redis中可以使用watch命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key。这样就可以对指定的key加乐观锁了。 注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了exec,discard,unwatch命令都会清除连接中的所有监视。

Redis中的事务(transaction)是一组命令的集合。事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行。Redis事务的实现需要用到 MULTI 和 EXEC 两个命令,事务开始的时候先向Redis服务器发送 MULTI 命令,然后依次发送需要在本次事务中处理的命令,最后再发送 EXEC 命令表示事务命令结束。Redis的事务是下面redis的4个方法来实现 : jedis = RedisUtil.getInstance().getJedis();

代码语言:javascript
复制
1).multi,开启Redis的事务,置客户端为事务态。

2).exec,提交事务,执行从multi到此命令前的命令队列,置客户端为非事务态。

3).discard,取消事务,置客户端为非事务态。

4).watch,监视键值对,作用时如果事务提交exec时发现监视的监视对发生变化,事务`将被取消。

参考https://www.cnblogs.com/jasonZh/p/9522772.html https://www.jianshu.com/p/06f1bce98451

代码语言:javascript
复制
我们在高并发使用redis时,我们不止需要采用分布式事务的模式,还需要采用乐观锁保证数据安全。
redis乐观锁的实现一定要伴随着redis事务。

话不多说直接上代码

redisTemplate.watch("key"); // 1
redisTemplate.multi();
redisTemplate.boundValueOps("key").set(""+id);
List<Object> list= redisTemplate.exec();
System.out.println(list);
if(list != null ){
    //操作成功
    System.out.println(id+"操作成功");
}else{
    //操作失败
    System.out.println(id+"操作失败");
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数据的锁定分为两种,第一种叫作悲观锁,第二种叫作乐观锁。
    • 一、悲观锁
    • 二、乐观锁
      • 乐观锁的具体实现模式:
      相关产品与服务
      云数据库 Redis
      腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档