今天带着学生学习了Redis的事务功能,Redis的事务与传统的关系型数据库(如MySQL)有所不同,Redis的事务不能回滚。

Redis中使用multi、exec、discard、watch、unwatch等命令来操作事务。

例如:

> MULTI

OK

> INCR aaa

QUEUED

> INCR bbb

QUEUED

> EXEC

1) (integer) 1

2) (integer) 1

multi命令表示启动事务(begin transaction),exec表示执行事务(commit),如果中间的操作有错误,有两种情形:

1.语法错误,表现为在EXEC执行前,命令不能正常添加到Queue中。例如,命令出现语法错误等。
2. 代码在执行的时候错误,表现为在EXEC执行后,命令不能正确执行。例如,将string当做list操作。此种操作比较奇怪,在redis事务中,并不会因为中间失败了导致整个不能执行,而是将正确的部分执行了。有种观点认为 Redis 处理事务的做法会产生 bug ,然而需要注意的是,在通常情况下,回滚并不能解决编程错误带来的问题,并且这类错误通常不会在生产环境中出现,所以 Redis 选择了更简单、更快速的无回滚方式来处理事务。

那么这种事务如何去实现秒杀功能呢。答案是使用watch,watch能监控某一个key的变化,在事务执行时,如果其他的client改变了这个可以所对应的值,将会导致当前client的事务不执行,即类似于乐观锁机制。

示例代码如下:

首先没有watch的代码:

示例为有10张优惠券,有多人来抢,需要提供秒杀功能。

首先在redis中设置一个key为num值为0:

命令为:set num 0

public class MyThread extends Thread {

@Override

public void run() {

for (int i = 0; i < 10; i++){

Jedis jedis = RedisConnection.getJedis();

String num = jedis.get("num");

int n = Integer.parseInt(num);

if (n < 10){

try {

Thread.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

jedis.incr("num");

String name = UUID.randomUUID().toString().replaceAll("-", "");

System.out.println(name + "抢到一张优惠券");

}

}

}

}

public class TestMain {

public static void main(String[] args) {

for (int i = 0; i < 5; i++){

MyThread thread = new MyThread();

thread.start();

}

}

}

当执行这种代码时,会发现会有超过10个人抢到优惠券。

加入watch时,代码如下,修改Mythred类:

public class MyThread extends Thread {

@Override

public void run() {

for (int i = 0; i < 10; i++){

Jedis jedis = RedisConnection.getJedis();

String watch = jedis.watch("num");

String num = jedis.get("num");

int n = Integer.parseInt(num);

if (n < 10){

try {

Thread.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

Transaction transaction = jedis.multi();

transaction.incr("num");

List<Object> list = transaction.exec();

String name = UUID.randomUUID().toString().replaceAll("-", "");

if (list == null || list.size() == 0){

System.out.println(watch + "==="+list+"----" + name + "手慢了,抢票失败");

}else {

System.out.println(watch + "==="+list+"----" + name + "抢到一张优惠券");

}

}

}

}

}

测试结果,你会发现,虽然一样会有多人去抢,但是始终只有10个人能正取的抢到。

Redis事务和实现秒杀功能的实现的更多相关文章

  1. php+redis实现电商秒杀功能

    这一次总结和分享用Redis实现分布式锁来完成电商的秒杀功能.先扯点个人观点,之前我看了一篇博文说博客园的文章大部分都是分享代码,博文里强调说分享思路比分享代码更重要(貌似大概是这个意思,若有误请谅解 ...

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

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

  3. redis使用watch完成秒杀抢购功能(转)

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

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

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

  5. thinkphp+redis实现秒杀功能

    好久没来整理文章了,闲了没事写篇文章记录下php+redis实现商城秒杀功能. 1,安装redis,根据自己的php版本安装对应的redis扩展(此步骤简单的描述一下) 1.1,安装 php_igbi ...

  6. Redis分布式锁实现简单秒杀功能

    这版秒杀只是解决瞬间访问过高服务器压力过大,请求速度变慢,大大消耗服务器性能的问题. 主要就是在高并发秒杀的场景下,很多人访问时并没有拿到锁,所以直接跳过了.这样就处理了多线程并发问题的同时也保证了服 ...

  7. spring boot:redis+lua实现生产环境中可用的秒杀功能(spring boot 2.2.0)

    一,秒杀需要具备的功能: 秒杀通常是电商中用到的吸引流量的促销活动方式 搭建秒杀系统,需要具备以下几点: 1,限制每个用户购买的商品数量,(秒杀价格为吸引流量一般会订的很低,不能让一个用户全部抢购到手 ...

  8. flask+redis实现抢购(秒杀)功能

    今天面试了 一家非常高大上的公司,问了我关于redis的实用性问题,但是答的不是很好,所以下午通过再次学习 redis,实现相关实用性功能的一种. 对于抢购功能,难点在于 抢购时 由于高并发请求,导致 ...

  9. redis 事务 及发布于订阅功能

    事务: Redis事务可以一次执行多个命令,事务具有以下特征: 1.隔离操作:事务中的所有命令都会序列化.按顺序地执行,不会被其他命令打扰. 2.原子操作:事务中的命令要么全部被执行,要么全部都不执行 ...

随机推荐

  1. tensorflow estimator API小栗子

    TensorFlow的高级机器学习API(tf.estimator)可以轻松配置,训练和评估各种机器学习模型. 在本教程中,您将使用tf.estimator构建一个神经网络分类器,并在Iris数据集上 ...

  2. gitignore不起作用

    .gitignore中已经标明忽略的文件目录下的文件,git push的时候还会出现在push的目录中,原因是因为在git忽略目录中,新建的文件在git中会有缓存,如果某些文件已经被纳入了版本管理中, ...

  3. 关于C#mvc用iis发布,虚拟目录的问题。

    mvc关于iis发布虚拟目录的问题,解决方法是修改代码中路径的方式,例如ajax中常用的为url:“/Home/Index”,可修改为 url: '@Url.Action("Index&qu ...

  4. 蓝图Blueprint

    ---恢复内容开始--- 蓝图: flask模块化处理操作和URL的方式 作用: 将不同的功能模块化,实现模块化应用 构建大型应用 优化项目结构 使用步骤 创建蓝图对象 对蓝图对象进行操作(注册路由; ...

  5. python操作samba

    最近在部署完xxl-job后,陆续将一些日常性执行的python脚本迁移到上面去:其中部分脚本涉及到对samaba的操作,先后尝试了pysmb.fs.smbfs.pysmbclient pysmb 安 ...

  6. R语言数值积分

    前两天对学习了R里面计算的基本范围,以及一些求解方程的方法,今天来看看积分,其实上个学期学了数值分析,对这部分的算法是有所了解的,当时是用matlab写了一遍,已经忘了怎么实现的了,现在用R重新写一遍 ...

  7. C++二维数组、指针、对象数组、对象指针

    项目中用到,随手记一下: 1.二维数组.与指针 创建二维数组指针的方式: a.已知一维的大小 1 int **array=new int *[rows]; 2 (for int i=0;i<ro ...

  8. SpringMVC云题库错题及答案汇总-2

    此题目考察的是SpringMVC-注解驱动控制器,注释类型的范围: A.处理requet uri 部分的注解: @PathVariable; B.处理request header部分的注解: @Req ...

  9. 原生js实现淘宝图片切换

    这个淘宝图片切换具体效果就是:鼠标移上底部一行中的小图片,上面大图片区域就会显示对应的图片. gif图片看起来还挺酷的,其实实现很简单,用原生js绑定事件改变大图片区域的src. 上代码,html部分 ...

  10. 结对作业_core组

    github地址:https://github.com/ljw-wakeup/expression_project2 对于这种结对的工作,由于有过电子设计实践的基础,大概知道建一个工程需要做的事,有点 ...