1、使用watch,采用乐观锁 
2、不使用悲观锁,因为等待时间非常长,响应慢 
3、不使用队列,因为并发量会让队列内存瞬间升高

package com.javartisan.concurrent;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.List;
import java.util.UUID;import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;/*** redis并发抢购测试** @author javartisan*/
public class RedisTest {public static void main(String[] args) {final String watchkeys = "watchkeys";ExecutorService executor = Executors.newFixedThreadPool(20);GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379, 10000, "root");final Jedis jedis = jedisPool.getResource();jedis.auth("root");jedis.set(watchkeys, "0");// 重置watchkeys为0jedis.del("setsucc", "setfail");// 清空抢成功的,与没有成功的jedis.close();for (int i = 0; i < 10000; i++) {// 测试一万人同时访问executor.execute(new MyRunnable(jedisPool));}executor.shutdown();}
}class MyRunnable implements Runnable {String watchkeys = "watchkeys";// 监视keysJedisPool jedisPool = null;public MyRunnable(JedisPool jedisPool) {this.jedisPool = jedisPool;}@Overridepublic void run() {Jedis jedis = jedisPool.getResource();try {<strong>jedis.watch(watchkeys);//代码块1 watchkeys</strong>String val = jedis.get(watchkeys);int valint = Integer.valueOf(val);String userifo = UUID.randomUUID().toString();if (valint < 10) {<strong>Transaction tx = jedis.multi();//代码块2 开启事务tx.incr("watchkeys");List<Object> list = tx.exec();//代码块3 提交事务,如果此时watchkeys被改动了,则返回emptyList</strong>if (list.size() > 0) {System.out.println("用户:" + userifo + "抢购成功,当前抢购成功人数:" + (valint + 1));/* 抢购成功业务逻辑 */jedis.sadd("setsucc", userifo);return;}}System.out.println("用户:" + userifo + "抢购失败");jedis.sadd("setfail", userifo);return;} catch (Exception e) {e.printStackTrace();} finally {jedis.close();}}}

Redis对事物的支持目前比较简单。Redis只能保证一个client发起的事务中的命令可以连续的执行,但后面命令出错前面不会回滚。而中间不会插入其他client的命令。当一个client在找一个连续中发出multi命令时,这个链接会进入一个事务上下文,该链接后续的命令不会立即执行,而是先放到队列中,当执行exec命令是,redis会顺序的执行队列中的所有命令。当如果队列中有命令错误,不会回滚。

乐观锁:大多数是基于数据版本(version)的记录机制实现的。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表添加一个”version”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号+1。此时,将提交数据的版本号与数据库表对应记录版本号进行比对,如果提交的数据版本号大于数据当前版本号,则予以更新,否则认为是过去数据。

在Redis中,使用watch命令实现乐观锁(watch key): 
watch命令会监视给定的key,当exec时,如果监视的key从调用watch后发生过变化,则事务会失败,也可以调用wathc多长监视多个key。这样就可以对指定key加乐观锁了。注意watch的可以是对整个连接有效的。事务也一样。如果连接断开,监视和事务都会被自动清除。当然exec,discard,unwatch命令都会清除连接中的所有监视。

Jedis中的exec方法实现源码:

public List<Object> exec() {client.exec();client.getAll(1); // Discard all but the last replyinTransaction = false;<strong>List<Object> unformatted = client.getObjectMultiBulkReply();</strong><strong>  if (unformatted == null) { //事务失败return Collections.emptyList();}</strong>List<Object> formatted = new ArrayList<Object>();for (Object o : unformatted) {try {formatted.add(generateResponse(o).get());} catch (JedisDataException e) {formatted.add(e);}}return formatted;}

https://www.cnblogs.com/leodaxin/p/9553988.html

https://blog.csdn.net/qq1013598664/article/details/70183908

redis使用watch秒杀抢购思路相关推荐

  1. Redis两种秒杀抢购思路

    方式一:使用DECR减库存 /** * 外卡进入减库存 * @param competitionQuarterInDTO * @return */@Overridepublic int otherCa ...

  2. 秒杀抢购场景下防止商品超卖的技术实现思路

    一. 秒杀抢购场景下防止商品超卖的技术实现思路 1. 通常解法 方案一: 在购买下单前先查询数据库库存是否大于0进行判断,有库存在进行减库存下单操作,反之下单失败. 具体做法:用户点击活动页面时,后台 ...

  3. php秒杀防重复中奖_PHP如何应对秒杀抢购高并发思路

    原标题:PHP如何应对秒杀抢购高并发思路 我们常用QPS(Query Per Second,每秒处理请求数)来衡量一个web应用的吞吐率,解决每秒数万次的高并发场景,这个指标非常关键. 举个栗子:假设 ...

  4. redis使用watch完成秒杀抢购功能

    redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...

  5. 简单的redis使用watch完成秒杀抢购功能

    2019独角兽企业重金招聘Python工程师标准>>> Redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和 ...

  6. 秒杀抢购案例,基于 Redis 实现

    目录 1.关于全局唯一 ID 生成器 1.1 需要满足的特性 1.2 代码实现 1.3 其他的唯一 ID 生成策略 2.实现秒杀下单 2.1 超卖问题的产生 2.2 超卖问题的分析与解决 2.21 悲 ...

  7. 秒杀抢购异步下单:基于Redis的消息队列秒杀抢购异步下单功能

    学习Redis时,练习的实战项目代码--基于Redis的Stream类型的秒杀抢购异步下单. 说明: Redis的stream类型的消息队列实现异步下单功能.Redis版本至少要5.0及以上版本才可以 ...

  8. Spring Boot + redis解决商品秒杀库存超卖,看这篇文章就够了

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:涛哥谈篮球 来源:toutiao.com/i68366119 ...

  9. redis如何解决秒杀超卖java_Spring Boot + redis解决商品秒杀库存超卖,看这篇文章就够了...

    作者:涛哥谈篮球 来源:toutiao.com/i6836611989607809548 问题描述 在众多抢购活动中,在有限的商品数量的限制下如何保证抢购到商品的用户数不能大于商品数量,也就是不能出现 ...

最新文章

  1. Windows Server 2008英文正式版安装体验
  2. Password-less logins with OpenSSH
  3. SAP alv 去掉标准按钮
  4. 查看db2数据库名linux,【名说】DB2数据库备份与恢复(linux环境)
  5. 有危害吗_涂料漆对身体有害吗?涂料漆危害怎么预防
  6. ARM Cotex-M4数据手册4---System Control
  7. freeswitch订阅会议相关通知
  8. mysql procedure prepare_mysql prepare 存储过程使用
  9. 《JavaScript高级程序设计(第2版)》
  10. 类和对象编程(五):友元函数
  11. 机器学习 决策树 监督_监督机器学习-决策树分类器简介
  12. 国外cpa广告联盟EMU-lead-cpa联盟详解(2)im搭建
  13. Vue实现在线编辑excel
  14. 中冠百年|家庭理财投资必备资金规划有哪些
  15. ZOJ 2975 Kinds of Fuwas(暴力)
  16. 像素 屏幕分辨率 摄像头分辨率
  17. 迎接新时代,维谛技术全面呈献硬核策略
  18. mysql中的BIT_LENGTH和LENGTH以及CHAR_LENGTH的区别
  19. windows:将网络共享文件夹映射为网络硬盘
  20. 先电openstack2.4云计算省赛任务一:iaas平台搭建任务

热门文章

  1. O2O助汪峰成功逆袭,汪峰最终上头条了
  2. Espressif IDE 及其 v2.4.0 新增功能—第二部分
  3. javascript单词
  4. Nginx 配置静态资源防盗链
  5. 复数的实部虚部与幅值相角之间的转换及python代码实现
  6. 链表操作演示程序(ege C语言)
  7. html怎么改文字方向,WPS文字中如何更改文字方向?
  8. 为什么你觉得FPGA难学?如何入门?
  9. 荣耀Magic5系列,至臻版安装谷歌服务框架,安装Google谷歌Play商店
  10. 门禁系统 java源代码_Java经典源码 门禁系统完整代码