示例代码是基于博客 https://blog.csdn.net/qq1013598664/article/details/70183908的错误案例修改而来,如果有问题望多多指点,错误代码可以去原文查阅,本文将会指出错误之处。

不多废话,直接上代码:

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 {jedis.watch(watchkeys);//代码块1 watchkeysString val = jedis.get(watchkeys);int valint = Integer.valueOf(val);String userifo = UUID.randomUUID().toString();if (valint < 10) {Transaction tx = jedis.multi();//代码块2 开启事务tx.incr("watchkeys");List<Object> list = tx.exec();//代码块3 提交事务,如果此时watchkeys被改动了,则返回emptyListif (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();}}}

  

 

原文错误之处在于对exec方法的处理,当事务被打断或者执行失败的话返回的是一个emptyList,并不是一个null,因此需要使用list.size判断事务状态。

Jedis中的exec方法实现源码:

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

  

Redis抢购成功数据:

抢购失败用户个数:

备注说明:

代码块1表示监督key,以准备执行事务,如果在事务执行期间该key对应的value被修改的话事务进行回滚。

代码块2到代码块3之间是开启事务执行命令并提交事务,在这个代码期间必须使用事务对象执行命令,否者会报错。即使用tx操作。

在事务中判断元素是否存在时候,返回的是一个Response对象,例如方法get:

redis.clients.jedis.RedisPipeline#get

  public Response<String> get(String key) {getClient(key).get(key);return getResponse(BuilderFactory.STRING);}

只能在事务执行完毕或者事务discard之后才可以get,不能再事务期间进行get。

秒杀系统结合限流系统一起处理效果会更好

转载于:https://www.cnblogs.com/leodaxin/p/9553988.html

基于Redis实现的抢购代码示例相关推荐

  1. Freemarker基于模板文件静态化代码示例

    Freemarker基于模板文件静态化代码示例

  2. [IE编程] 多页面基于IE内核浏览器的代码示例

    有不少人发信问这个问题,我把答案贴在这里: 建议参考 WTL (Windows Template Library) 的代码示例工程 TabBrowser  (在WTL目录/Samples/TabBro ...

  3. echarts python源码_基于Django快速集成Echarts代码示例

    1.在线定制下载echarts 2.创建一个django项目或者在已有的项目 配置文件中确保数据库配置.static配置.与添加项目名到INSTALLED_APPS下. 配置静态文件目录static, ...

  4. 面试中又被问到Redis如何实现抢购,赶快代码实现一波吧!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:硬刚一周,3W字总结,一年的经验告诉你如何准备校招! 个人原创100W+访问量博客:点击前往,查看更多 作者:g ...

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

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

  6. 送书 | 你一定能看懂的算法基础书(代码示例基于Python)

    本文引自图灵教育<算法图解> 你一定能看懂的算法基础书:代码示例基于Python:400多个示意图,生动介绍算法执行过程:展示不同算法在性能方面的优缺点:教会你用常见算法解决每天面临的实际 ...

  7. java克鲁斯卡尔算法_Java语言基于无向有权图实现克鲁斯卡尔算法代码示例

    所谓有权图,就是图中的每一条边上都会有相应的一个或一组值.通常情况下,这个值只是一个数字 如:在交通运输网中,边上的权值可能表示的是路程,也可能表示的是运输费用(显然二者都是数字).不过,边上的权值也 ...

  8. jedispool redis哨兵_通过java哨兵JedisSentinelPool代码示例连接对配置的redis哨兵主从模式进行测试验证...

    一.前言 本文章通过关于java的jedis(2.6.0)的redis客户端连接驱动包,对配置的redis哨兵+主从读写模式配置进行示例代码验证,详细参见具体配置步骤&示例代码说明部分. 二. ...

  9. redis分布式锁java代码_基于redis实现分布式锁

    " 在上一篇文章中介绍了动态配置定时任务,其中的原理跟spring 定时任务注解@Scheduled一样的,都是通过线程池和定义执行时间来控制.来思考一个问题,如果我们的定时任务在分布式微服 ...

最新文章

  1. 【ACM】杭电OJ 2012。
  2. 全球工业互联网十大最具成长性技术
  3. 一次简单的Java服务性能优化,实现压测 QPS 翻倍
  4. 最近看的篇文章,年过三十,感触很深
  5. android分享的主标题,Android 自定义标题栏(title栏)
  6. win7 php mysql扩展名_Win7 配置Apache+PHP+Mysql环境
  7. fedora在此处打开终端
  8. centos7的网卡配置 实用经典总结
  9. sqlserver object_id()函数
  10. IOS开发-关于自定义TabBar条
  11. Caffe︱构建lmdb数据集、binaryproto均值文件及各类难辨的文件路径名设置细解
  12. 计算机配置更新怎么关闭,如何关闭戴尔电脑自动更新系统配置
  13. 微软笔记本服务器怎么重装系统,微软Surface Book重装win10系统教程
  14. [源码阅读]解析Anime(JS动画库)核心(2)
  15. pythonwin7下载教程_如何在win7下安装Python及配置!python win7下载教程
  16. 过去七年,美国护照排名从榜首滑落至第7位
  17. 2019年英语四级作文
  18. es java api 进行聚合+桶聚合查询
  19. 自带设备(BYOD)能用零信任框架吗?
  20. 大学毕业小总结以及感想

热门文章

  1. python/socket编程之粘包
  2. centos 6.8 下安装redmine(缺陷跟踪系统)
  3. Vijos1775 CodeVS1174 NOIP2009 靶形数独
  4. NOIP2013/day1/1/转圈游戏
  5. [Erlang危机](4.4)命名管道
  6. 网络协议:ARP协议
  7. hive常见的DML操作
  8. (229)DPU加速数据处理
  9. (93)异步FIFO结构,为什么用格雷码? ,面试必问(十七)(第19天)
  10. (93)Verilog HDL系统函数和任务:$fread