Redis事务和实现秒杀功能的实现
今天带着学生学习了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事务和实现秒杀功能的实现的更多相关文章
- php+redis实现电商秒杀功能
这一次总结和分享用Redis实现分布式锁来完成电商的秒杀功能.先扯点个人观点,之前我看了一篇博文说博客园的文章大部分都是分享代码,博文里强调说分享思路比分享代码更重要(貌似大概是这个意思,若有误请谅解 ...
- redis使用watch完成秒杀抢购功能
Redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...
- redis使用watch完成秒杀抢购功能(转)
redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...
- redis使用watch完成秒杀抢购功能:
redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...
- thinkphp+redis实现秒杀功能
好久没来整理文章了,闲了没事写篇文章记录下php+redis实现商城秒杀功能. 1,安装redis,根据自己的php版本安装对应的redis扩展(此步骤简单的描述一下) 1.1,安装 php_igbi ...
- Redis分布式锁实现简单秒杀功能
这版秒杀只是解决瞬间访问过高服务器压力过大,请求速度变慢,大大消耗服务器性能的问题. 主要就是在高并发秒杀的场景下,很多人访问时并没有拿到锁,所以直接跳过了.这样就处理了多线程并发问题的同时也保证了服 ...
- spring boot:redis+lua实现生产环境中可用的秒杀功能(spring boot 2.2.0)
一,秒杀需要具备的功能: 秒杀通常是电商中用到的吸引流量的促销活动方式 搭建秒杀系统,需要具备以下几点: 1,限制每个用户购买的商品数量,(秒杀价格为吸引流量一般会订的很低,不能让一个用户全部抢购到手 ...
- flask+redis实现抢购(秒杀)功能
今天面试了 一家非常高大上的公司,问了我关于redis的实用性问题,但是答的不是很好,所以下午通过再次学习 redis,实现相关实用性功能的一种. 对于抢购功能,难点在于 抢购时 由于高并发请求,导致 ...
- redis 事务 及发布于订阅功能
事务: Redis事务可以一次执行多个命令,事务具有以下特征: 1.隔离操作:事务中的所有命令都会序列化.按顺序地执行,不会被其他命令打扰. 2.原子操作:事务中的命令要么全部被执行,要么全部都不执行 ...
随机推荐
- 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 ...
- python学习博客地址集合。。。
python学习博客地址集合... 老师讲课博客目录 http://www.bootcdn.cn/bootstrap/ bootstrap cdn在线地址 http://www.cnblogs. ...
- TP自动提取关键词
protected function _before_insert(&$data, $option) { $data['create_time'] = time(); ...
- SQL-55 分页查询employees表,每5行一页,返回第2页的数据
题目描述 分页查询employees表,每5行一页,返回第2页的数据CREATE TABLE `employees` (`emp_no` int(11) NOT NULL,`birth_date` d ...
- change事件同一文件多次选中
最近在做图片上传的时候,碰到了一点问题,那就是选择内容相同,change事件执行不了 网上搜索了答案,使用off('change')好像也不行 最终找到一种解决办法 使用replaceWith重置in ...
- JAVA接口里面的变量
在interface里面的变量都是public static final 的.所以你可以这样写:public static final int i=10;或则int i=10:(可以省略掉一部分) 注 ...
- Spring源码学习(5)—— bean的加载 part 2
之前归纳了从spring容器的缓存中直接获取bean的情况,接下来就需要从头开始bean的加载过程了.这里着重看单例的bean的加载 if(ex1.isSingleton()) { sharedIns ...
- nginx 添加代理
1 确认安装路径 ps aux | grep nginx 2.进入配置目录 3.使用vi编辑配置文件 如果是新增,可以参考其他配置,5yy复制相应行,p粘贴,然后修改内容后:wq保存退出 4.验证配置 ...
- Ubuntu的显示问题不全解决
首先我们安装的是Ubuntu 16.04版本.最开始一直不能解分辨率问题,导致信息显示不全 利用xrandr -s 1369x768(中间x是乘号不是英文字母) 命令来设置分辨率, 需注意的是: 1. ...
- .net 服务因为GC时遇到的问题和解决办法
1.问题: .net单一服务中,大量的请求访问后台服务,多线程处理请求,但每个线程都可能出现超时的现象.记录超时日志显示,超时可能在序列化时,Socket异步发送AsyncSend数据时,普通业务处理 ...