秒杀系统数据同步(保证不多卖)
2015-11-25 18:10
253 查看
参考:Java实现watch multi的方式
/article/3896136.html
参考:Redis命令参考——事务(transaction)
http://redisdoc.com/topic/transaction.html
参考:Redis exception: Cannot use Jedis when in Multi.(Java语言)
http://dmitrijs.artjomenko.com/2012/04/redis-exception-cannot-use-jedis-when.html
参考:Python实现watch multi的方式
http://xiaorui.cc/2015/05/09/python%E4%BD%BF%E7%94%A8redis%E4%BA%8B%E5%8A%A1%E6%97%B6%E9%81%87%E5%88%B0multi%E3%80%81watch%E5%92%8C%E9%94%81%E7%9A%84%E9%97%AE%E9%A2%98/
下一步工作:
参考:python使用redis实现协同控制的分布式锁
http://xiaorui.cc/2014/12/19/python%E4%BD%BF%E7%94%A8redis%E5%AE%9E%E7%8E%B0%E5%8D%8F%E5%90%8C%E6%8E%A7%E5%88%B6%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/
参考:基于Redis实现分布式锁
/article/2780586.html
Redis 中的watch可以在事务前对数据进行监控,如果在事务执行前,该数据发生改变,则事务不执行。刚好能满足我们的要求。看了很多代码,对watch功能还不是很理解,因为网上很多写的帖子都没有明确指出多客户端(理解之后发现还是有写的),所以不明白的可以参见下面的例子,是用Java写的。以下代码可以保证库存不多卖。
在redis中设置一个键为mykey,值为1000的变量,
/article/3896136.html
参考:Redis命令参考——事务(transaction)
http://redisdoc.com/topic/transaction.html
参考:Redis exception: Cannot use Jedis when in Multi.(Java语言)
http://dmitrijs.artjomenko.com/2012/04/redis-exception-cannot-use-jedis-when.html
参考:Python实现watch multi的方式
http://xiaorui.cc/2015/05/09/python%E4%BD%BF%E7%94%A8redis%E4%BA%8B%E5%8A%A1%E6%97%B6%E9%81%87%E5%88%B0multi%E3%80%81watch%E5%92%8C%E9%94%81%E7%9A%84%E9%97%AE%E9%A2%98/
下一步工作:
参考:python使用redis实现协同控制的分布式锁
http://xiaorui.cc/2014/12/19/python%E4%BD%BF%E7%94%A8redis%E5%AE%9E%E7%8E%B0%E5%8D%8F%E5%90%8C%E6%8E%A7%E5%88%B6%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/
参考:基于Redis实现分布式锁
/article/2780586.html
正文
东西不多卖
秒杀系统需要保证东西不多卖,关键是在多个客户端对库存进行减操作时,必须加锁。Redis中的Watch刚好可以实现一点。首先我们需要获取当前库存,只有库存中的食物小于购物车的数目才能对库存进行减。在高并发的情况下会出现某时刻查询库存够的,但下一时刻另外一个线程下单了,对库存进行减操作,刚好小于上个线程的购物车数目。照理现在的状态是不能下单成功的,因为库存已经不够了,但上一线程仍然认为数量还够,对库存进行减操作,从而导致库存出现负数的情况。如何避免?Redis 中的watch可以在事务前对数据进行监控,如果在事务执行前,该数据发生改变,则事务不执行。刚好能满足我们的要求。看了很多代码,对watch功能还不是很理解,因为网上很多写的帖子都没有明确指出多客户端(理解之后发现还是有写的),所以不明白的可以参见下面的例子,是用Java写的。以下代码可以保证库存不多卖。
在redis中设置一个键为mykey,值为1000的变量,
public class Main { public static void main(String[] args) { new MyThread().start(); new MyThread().start(); new MyThread().start(); new MyThread().start(); new MyThread().start(); new MyThread().start(); new MyThread().start(); new MyThread().start(); new MyThread().start(); new MyThread().start(); } } class MyThread extends Thread { Jedis jedis = null; @Override public void run() { // TODO Auto-generated method stub while (true) { System.out.println(Thread.currentThread().getName()); jedis = RedisUtil.getJedis(); try { int stock = Integer.parseInt(jedis.get("mykey")); if (stock > 0) { jedis.watch("mykey"); Transaction transaction = jedis.multi(); transaction.set("mykey", String.valueOf(stock - 1)); List<Object> result = transaction.exec(); if (result == null || result.isEmpty()) { System.out.println("Transaction error...");// 可能是watch-key被外部修改,或者是数据操作被驳回 } } else { System.out.println("库存为0"); break; } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); RedisUtil.returnResource(jedis); }finally{ RedisUtil.returnResource(jedis); } } } }
Redis保证从数据只加载一次
我这里碰到的需求是一开始要从Mysql数据库中导入数据到Redis,由于有多台服务器,不进行控制会对数据进行多次加载,所以我们可以设置一个键值进行控制。import redis.clients.jedis.Jedis; import redis.clients.jedis.Response; import redis.clients.jedis.Transaction; public class Main { public static void main(String[] args) { new lock().start(); new lock().start(); new lock().start(); new lock().start(); new lock().start(); new lock().start(); new lock().start(); new lock().start(); new lock().start(); new lock().start(); } } class lock extends Thread{ @Override public void run() { // TODO Auto-generated method stub System.out.println(Thread.currentThread().getName()); Jedis jedis = null; try { jedis = RedisUtil.getJedis(); if(jedis.setnx("look", "1") == 1){ jedis.set("food", Thread.currentThread().getName()); }else{ System.out.println(Thread.currentThread().getName() + "未访问"); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); RedisUtil.returnResource(jedis); }finally{ RedisUtil.returnResource(jedis); } } }
相关文章推荐
- mfc dll
- springMVC获取file,几种转换
- java多线程
- Clicker
- 針對新版OWASP十大網頁應用弱點逐一查驗
- libpcap在centos安装
- jquery基础
- ECharts切换主题
- java基础<八>-------多态
- mysql防止多字段重复插入
- Revit二次开发入门——通过过滤器获取元素
- java将白色背景图片转换成无色
- android电池管理系统
- CyclicBarrier的用法
- iOS中protobuf和tcp长链接(AsyncSocket)scoket配合使用
- 公元2015年11月25日。阴。
- ffmpeg添加水印的方法举例 (砖)
- File 类
- java刷新页面不回到顶部
- 图形变换之使用矩阵变换