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.原子操作:事务中的命令要么全部被执行,要么全部都不执行 ...
随机推荐
- vue双向数据绑定
本文来源于 https://jingyan.baidu.com/article/91f5db1b0c2a4f1c7f05e3a8.html
- [Oracle][DATAGUARD]关于REDO_TRANSPORT_USER参数
大家可能已经知道,在Oracle的DATAGUARD(这里指的是PHYSICAL STANDBY)环境中,Primary端会把生成的REDO传到Standby端,然后由Standby端的MRP进程应用 ...
- 安装CaffeOnSpark过程中遇到的问题及解决方案
安装教程来自 http://blog.csdn.net/sadonmyown/article/details/72781393 首先,我使用的节点环境是ubuntu 16.04.1,事先 成功安装了s ...
- 报表工具highcharts使用心得
公司让做一个报表页面,搜索了下发现highcharts比较符合业务需求,下面就说一下使用心得. $('#container').highcharts({ title: { text: '部门统计图' ...
- vivado封装IP
reference: https://www.cnblogs.com/mouou/p/5851736.html 1.新建一个测试工程 工程化的设计方法是离不开工程的,第一步往往都是新建工程,后面我 ...
- .net webService保存全局变量中
遇到坑,然后找到解决方案,我就习惯做个记录. 情景:通过webservice调用一个第三方的库,在初始化第三方库的时候需要花费较长时间 目的:希望通过初始化一次,缓存下来,下次直接调用,而不必每次初始 ...
- 自己动手写CPU——寄存器堆、数据存储器(基于FPGA与Verilog)
上一篇写的是基本的设计方案,由于考研复习很忙,不知道下一次什么时候才能打开博客,今天就再写一篇.写一写CPU中涉及到RAM的部件,如寄存器堆.数据存储器等. 大家应该在大一刚接触到计算机的时候就知道R ...
- hibernate基本的配置与验证
导入jar包与mysql驱动包 javaBean src/com/crazyit/app/domain/News.java package com.crazyit.app.domain; import ...
- oracle中创建数据库
一.在Oracle中创建数据库之前先改一下虚拟机的IP地址,以便访问 2. 3. 3.1 3.2 3.3 3.4 创建完成:输入sqlplus sys/123456 as sysdba测试
- DFS和BFS
BFS 代码步骤: 1.写出每个点和每个点的邻接点的对应关系 2.方法参数:传一个对应关系和起始点 3.创建一个队列,然后每次都移除第一个,然后把移除的邻接点添加进去,打印取出的第一个,然后循环,一直 ...