今天带着学生学习了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. Unable to determine the device handle for GPU 0000:01:00.0: GPU is lost.问题排坑

    在运行maskrcnn时,会碰到训练不动的问题,就卡在这儿 UserWarning: Converting sparse IndexedSlices to a dense Tensor of unkn ...

  2. python学习博客地址集合。。。

    python学习博客地址集合...   老师讲课博客目录 http://www.bootcdn.cn/bootstrap/  bootstrap cdn在线地址 http://www.cnblogs. ...

  3. TP自动提取关键词

    protected function _before_insert(&$data, $option) {        $data['create_time'] = time();       ...

  4. SQL-55 分页查询employees表,每5行一页,返回第2页的数据

    题目描述 分页查询employees表,每5行一页,返回第2页的数据CREATE TABLE `employees` (`emp_no` int(11) NOT NULL,`birth_date` d ...

  5. change事件同一文件多次选中

    最近在做图片上传的时候,碰到了一点问题,那就是选择内容相同,change事件执行不了 网上搜索了答案,使用off('change')好像也不行 最终找到一种解决办法 使用replaceWith重置in ...

  6. JAVA接口里面的变量

    在interface里面的变量都是public static final 的.所以你可以这样写:public static final int i=10;或则int i=10:(可以省略掉一部分) 注 ...

  7. Spring源码学习(5)—— bean的加载 part 2

    之前归纳了从spring容器的缓存中直接获取bean的情况,接下来就需要从头开始bean的加载过程了.这里着重看单例的bean的加载 if(ex1.isSingleton()) { sharedIns ...

  8. nginx 添加代理

    1 确认安装路径 ps aux | grep nginx 2.进入配置目录 3.使用vi编辑配置文件 如果是新增,可以参考其他配置,5yy复制相应行,p粘贴,然后修改内容后:wq保存退出 4.验证配置 ...

  9. Ubuntu的显示问题不全解决

    首先我们安装的是Ubuntu 16.04版本.最开始一直不能解分辨率问题,导致信息显示不全 利用xrandr -s 1369x768(中间x是乘号不是英文字母) 命令来设置分辨率, 需注意的是: 1. ...

  10. .net 服务因为GC时遇到的问题和解决办法

    1.问题: .net单一服务中,大量的请求访问后台服务,多线程处理请求,但每个线程都可能出现超时的现象.记录超时日志显示,超时可能在序列化时,Socket异步发送AsyncSend数据时,普通业务处理 ...