面试官问:如何防超卖,有几种实现方式

面试官问:如何防超卖,有几种实现方式

大家好,又见面了,我是全栈君。

场景

面试官问:如何防超卖,有几种实现方式

第一种方法 悲观锁

悲观并发控制(又名 “悲观锁”,Pessimistic Concurrency Control,缩写 “PCC”)是一种并发控制的方法。它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作读某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。

悲观并发控制主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。

竹子,公众号:码农编程进阶笔记php程序员面试题(偏中级面试题)

简而言之,悲观锁主要用于保护数据的完整性。当多个事务并发执行时,某个事务对数据应用了锁,则其他事务只能等该事务执行完了,才能进行对该数据进行修改操作。

update goods set num = num - 1 WHERE id = 1001 and num > 0

假设现在商品只剩下一件了,此时数据库中 num = 1;

但有 100 个线程同时读取到了这个 num = 1,所以 100 个线程都开始减库存了。

但你会最终会发觉,其实只有一个线程减库存成功,其他 99 个线程全部失败。

需要注意的是,FOR UPDATE 生效需要同时满足两个条件时才生效:

  • 数据库的引擎为 innoDB

  • 操作位于事务块中(BEGIN/COMMIT)

悲观锁采用的是「先获取锁再访问」的策略,来保障数据的安全。但是加锁策略,依赖数据库实现,会增加数据库的负担,且会增加死锁的发生几率。此外,对于不会发生变化的只读数据,加锁只会增加额外不必要的负担。在实际的实践中,对于并发很高的场景并不会使用悲观锁,因为当一个事务锁住了数据,那么其他事务都会发生阻塞,会导致大量的事务发生积压拖垮整个系统。


第二种办法 乐观锁

select version from goods WHERE id= 1001;

update goods set num = num - 1, version = version + 1 WHERE id= 1001 AND num > 0 AND version = @version(上面查到的version);

这种方式采用了版本号的方式,其实也就是 CAS 的原理。

假设此时 version = 100, num = 1; 100 个线程进入到了这里,同时他们 select 出来版本号都是 version = 100。

然后直接 update 的时候,只有其中一个先 update 了,同时更新了版本号。

那么其他 99 个在更新的时候,会发觉 version 并不等于上次 select 的 version,就说明 version 被其他线程修改过了。那么我就放弃这次 update


第三种方法 redis 消息队列

在秒杀的情况下,高频率的去读写数据库,会严重造成性能问题。所以必须借助其他服务, 利用 redis 的单线程预减库存。比如商品有 100 件。那么我在 redis 存储一个 k,v。例如

每一个用户线程进来,key 值就减 1,等减到 0 的时候,全部拒绝剩下的请求。

那么也就是只有 100 个线程会进入到后续操作。所以一定不会出现超卖的现象。


第四种办法 redis 分布式锁

$expire = 10;//有效期10秒
$key = 'lock';//key
$value = time() + $expire;//锁的值 = Unix时间戳 + 锁的有效期
$lock = $redis->setnx($key, $value);
//判断是否上锁成功,成功则执行下步操作
if(!empty($lock))
{
//下单逻辑...
}

面试官问:如何防超卖,有几种实现方式

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/111437.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • Layui 弹出层插件

    Layui 弹出层插件Layui弹出层插件开发工具与关键技术:VisualStudio2015–Layui作者:廖亚星撰写时间:2019年6月4日这段时间在做项目页面的搭建,在页面的操作中,会出现很多的弹出层,这能使用户在一个页面中执行更多的操作,而我的项目里面用的弹出层是Layui里面的弹出层插件。Layui的弹出层插件可以作为独立组件使用,也可以Layui模块化使用基本参数:type—…

    2022年6月13日
  • Java finalize方法使用

    Java finalize方法使用《JAVA编程思想》:java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize()。         (1).对象不一定会被回收。      (2).垃圾回收不是析构函数。      (3).垃圾回收只与内存有关。

    2022年9月19日
  • rcep协议内容_ptp协议

    rcep协议内容_ptp协议展开全部(1)合同的含义合同是当事人或当事双方之间设立、变更、终止民事关系的协议。依法62616964757a686964616fe78988e69d8331333363373036成立的合同,受法律保护。合同具有如下法律特征:①合同是两个或两个以上的、法律地位平等的当事人意思表示一致的协议;②合同以产生、变更或终止债权债务关系为目的;③合同是一种民事法律行为。在合同中,一般用甲方、乙方来指代交易…

    2022年9月6日
  • spring boot dubbo配置(上古卷轴5基础整合包)

    SpringBoot整合Dubbo3.0基础配置(dubbo-spring-boot-starter)一、说明众所周知,阿里早已把dubbo捐赠给了Apache,现在dubbo由Apache在维护更新,dubbo也已经成了Apache下的顶级项目。所以本demo项目所依赖的坐标是Apache官方最新的3.0.4坐标。<dependency><groupId>org.apache.dubbo</groupId><artifac

    2022年4月10日
  • 国内CMS技术发展的外在表现形式「建议收藏」

    国内CMS技术发展的外在表现形式「建议收藏」网站作为企事业单位的网上名片已经成为必需。大多数单位都选择利用成熟的CMS(内容管理系统)交给专业的公司或者本单位负责人(相当于站长)建设自己的网站。国内CMS技术的不断发展的外在表现,以便站长和建站公司选择合适的CMS系统建设更强大的网站。我建站时用过很多CMS系统,各有各的特点。现在之所以选择主要用We7的CMS是觉得在以下方面还是不错的。一产品成熟度。据我了解We7CMS系统

    2022年5月18日
  • jdbc fetchsize_jdbc和odbc的关系

    jdbc fetchsize_jdbc和odbc的关系DBUtilscommons-dbutils是Apache组织提供的一个开源JDBC工具类库,封装了针对于数据库的增删改查操作APIQueryRunnerResulSetHandlerDbutils插入举例Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JBBCUtils.getConnections3();

    2022年8月8日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号