示例代码是基于博客 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为0
jedis.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";// 监视keys
JedisPool jedisPool = null; public MyRunnable(JedisPool jedisPool) {
this.jedisPool = jedisPool;
} @Override
public void run() {
Jedis jedis = jedisPool.getResource(); try { jedis.watch(watchkeys);//代码块1 watchkeys String 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被改动了,则返回emptyList
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();
} } }

  

 

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

Jedis中的exec方法实现源码:

 public List<Object> exec() {
client.exec();
client.getAll(1); // Discard all but the last reply
inTransaction = 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。

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

基于Redis实现的抢购代码示例的更多相关文章

  1. 基于jQuery表格增加删除代码示例

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 一种基于Redis的10行代码实现IP频率控制方法

    优点:可支持海量访问的频率控制,只需要增加Redis机器,单个Redis节点(只占用一个cpu core)即可支持10万/s以上的处理. 基于IP频率限制是种常见需求,基于Redis可以十分简单实现对 ...

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

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

  4. 阿里云PHP Redis代码示例

    测试代码示例 <?php /* 这里替换为连接的实例host和port */ $host = "localhost"; $port = 6379; /* 这里替换为实例id和 ...

  5. [转载]基于Redis的Bloomfilter去重(附Python代码)

    前言: “去重”是日常工作中会经常用到的一项技能,在爬虫领域更是常用,并且规模一般都比较大.去重需要考虑两个点:去重的数据量.去重速度.为了保持较快的去重速度,一般选择在内存中进行去重. 数据量不大时 ...

  6. socket模块实现基于UDP聊天模拟程序;socketserver模块实现服务端 socket客户端代码示例

    socket模块 serSocket.setblocking(False) 设置为非阻塞: #coding=utf-8 from socket import * import time # 用来存储所 ...

  7. Redis学习手册(实例代码)

    在之前的博客中已经非常详细的介绍了Redis的各种操作命令.运行机制和服务器初始化参数配置.本篇博客是该系列博客中的最后一篇,在这里将给出基于Redis客户端组件访问并操作Redis服务器的代码示例. ...

  8. 分布式锁与实现(一)——基于Redis实现 【比较靠谱】

    转: 分布式锁与实现(一)——基于Redis实现 概述 目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题.分布式的CAP理论告诉我们“任何一个分布式系统 ...

  9. RedLock.Net - 基于Redis分布式锁的开源实现

    工作中,经常会遇到分布式环境中资源访问冲突问题,比如商城的库存数量处理,或者某个事件的原子性操作,都需要确保某个时间段内只有一个线程在访问或处理资源. 因此现在网上也有很多的分布式锁的解决方案,有数据 ...

随机推荐

  1. [EOJ439] 强制在线

    Description 见EOJ439 Solution 先考虑不强制在线怎么做. 按询问区间右端点排序,从左往右扫,维护所有后缀的答案. 如果扫到 \(a[i]\),那么让统计个数的 \(cnt[a ...

  2. C++多重继承的构造执行顺序

    一个类,它可能有基类,也可能存在多个基类,这些类里面还可能是虚拟基类,并且在类的本身也可能存在对象成员.那么所涉及的这些类或对象成员会以什么样的顺序来调用它们各自的构造函数呢?今天我们就来举例分析下. ...

  3. PowerDesigner反向生成物理数据模型

    什么是PowerDesigner Power Designer 是Sybase公司的CASE工具集,使用它可以方便地对管理信息系统进行分析设计,它几乎包括了数据库模型设计的全过程.利用Power De ...

  4. 《Visual C# 从零开始学》

    书名 <Visual C# 从零开始学> 图片 时间 2017年4月-5月 学习 对c#的基础语法有了一个较为完全的了解,总体还算顺利没有遇到理解不了的,感觉最好上手的是做windos窗体 ...

  5. 【开发工具之eclipse】8、The word is not correctly spelled。强迫症看着很难受

    eclipse出现了极其让我郁闷的错误,"The word is not correctly spelled" 我讨教过一些朋友以后,还是没有得到答案,我就纳闷了.然后我继续将代码 ...

  6. Adding a struct into an array(stackoverflow)

    Question: So lets say I have a struct like this: struct example_structure { int thing_one; int thing ...

  7. CTO 之“六脉神剑”

    他深谙电商之道,从零打造 1 号店网站及供应链系统,以技术引领业务发展.他是欧电云创始人韩军,下面将由他分享完美 CTO “六脉神剑”的经验之谈. 首先,从对 CTO 的一个认识误区讲起. 不写代码的 ...

  8. canvas-tangram.html

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. deepin使用笔记-解决蓝牙设备开机自动开启的问题

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 1.安装蓝牙驱动管理 #apt-get install blueman 2.打开蓝牙驱动管理,关闭设备 3.关闭蓝牙开机启动服务 ...

  10. Jenkins报错'Gradle build daemon disappeared unexpectedly'的问题解决

    在将项目集成到 Jenkins 后,经常会出现不稳定的构建,Jenkins 控制台输出的错误信息为:Gradle build daemon disappeared unexpectedly (it m ...