参考《redis实战》redis
一、商品交易的主体是我的,我的拥有姓名、资产属性。
二、每一个人都有N个商品,每一个商品都有惟一的商品编号。
三、容许商品投放到市场进行交易,一经投放,则商品从我的转移到市场,市场的商品按照价格排序。
四、交易须要判断资产是否足够,若是足够,商品从市场转移到买家
五、商品从我的到市场,或者市场到我的,都须要事务判断
能够用键值对保存姓名和资产信息,主键为用户的id,hincrBy方法对资产进行增长或减小。如下是hmset、hgetall、hincrBy的用法。code
// 赋值 local:0>hmset person:1 name zhangsan funds 100 "OK" // 显示hash内容 local:0>hgetall person:1 1) "name" 2) "zhangsan" 3) "funds" 4) "100" // 对hash的某个key的值进行相加 local:0>hincrBy person:1 funds 20 "120" // 显示hash内容 local:0>hgetall person:1 1) "name" 2) "zhangsan" 3) "funds" 4) "120"
能够用集合来存储商品,主键是商品的id,集合里放商品的编号。如下是sadd、smembers、sismember、srem的用法。排序
// 加入集合 local:0>sadd package:1 itemX "1" local:0>sadd package:1 itemY "1" local:0>sadd package:1 itemZ "1" // 显示集合元素 local:0>smembers package:1 1) "itemZ" 2) "itemX" 3) "itemY" // 集合是否存在某个元素,1为是 local:0>sismember package:1 itemX "1" // 移除集合的元素 local:0>srem package:1 itemX "1" // 集合是否存在某个元素,0为否 local:0>sismember package:1 itemX "0" // 显示集合元素 local:0>smembers package:1 1) "itemZ" 2) "itemY"
市场的商品排序,须要按价格排序,因此能够用有序集合。如下是zadd、zrevrange、zrem的用法。事务
// 新增元素 local:0>zadd market: 10 itemX.1 "1" local:0>zadd market: 11 itemY.1 "1" local:0>zadd market: 12 itemY.2 "1" // 从高到低排序 local:0>zrevrange market: 0 -1 withscores 1) "itemY.2" 2) "12" 3) "itemY.1" 4) "11" 5) "itemX.1" 6) "10" // 移除 local:0>zrem market: itemY.1 "1" local:0>zrevrange market: 0 -1 withscores 1) "itemY.2" 2) "12" 3) "itemX.1" 4) "10"
从hash取出资产,跟商品金额进行判断rem
在redis中,事务的开始是以MULTI开始,EXEC结束。在事务之间能够传输多个命令,可是实际上这些命令并不会被执行,直到调用EXEC的时候才会执行。
redis还提供了WATCH和UNWATCH对key进行监控和取消监控,若是事务执行以前,这些key被改动,则事务将会被中断。
UNWATCH在WATCH以后以及MULTI前取消对key的监控,DISCARD在MULTI执行以后,EXEC执行以前放弃执行事务块内的全部命令。
经过watch监听数据,而不是直接加锁,雷同于CAS的乐观锁和synchronized的悲观锁。get
@Test public void person() { Map<String, String> zhangsanMap = new HashMap(); zhangsanMap.put("name", "张三"); zhangsanMap.put("funds", "100"); JedisUtils.hmset("person:1", zhangsanMap); Map<String, String> lisiMap = new HashMap(); lisiMap.put("name", "李四"); lisiMap.put("funds", "10"); JedisUtils.hmset("person:2", lisiMap); System.out.println("张三的信息:" + JedisUtils.hgetAll("person:1")); System.out.println("李四的信息:" + JedisUtils.hgetAll("person:2")); }
@Test public void personPackage() { // 张三的商品 JedisUtils.sadd("package:1", "itemX"); JedisUtils.sadd("package:1", "itemY"); JedisUtils.sadd("package:1", "itemZ"); System.out.println("张三的商品:" + JedisUtils.smembers("package:1")); // 李四的商品 JedisUtils.sadd("package:2", "itemA"); JedisUtils.sadd("package:2", "itemB"); JedisUtils.sadd("package:2", "itemC"); System.out.println("李四的商品:" + JedisUtils.smembers("package:2")); }
@Test public void putMarket() { System.out.println("张三的商品:" + JedisUtils.smembers("package:1")); System.out.println("市场的商品:" + JedisUtils.zrangeWithScores("market:", 0, -1)); while (true) { Jedis jedis = JedisUtils.watch("package:1"); // 已经不存在了,则不监听 if (!JedisUtils.sismember("package:1", "itemX")) { jedis.unwatch(); break; } Transaction transaction = jedis.multi(); // 张三的商品移除 transaction.srem("package:1", "itemX"); // 市场的商品增长 transaction.zadd("market:", 8, "itemX.1"); List<Object> exec = transaction.exec(); // 不为空说明执行成功,跳出循环 if (null != exec) { break; } } System.out.println("张三的商品:" + JedisUtils.smembers("package:1")); System.out.println("市场的商品:" + JedisUtils.zrangeWithScores("market:", 0, -1)); }
@Test public void getMarket() { System.out.println("张三的信息:" + JedisUtils.hgetAll("person:1")); System.out.println("李四的信息:" + JedisUtils.hgetAll("person:2")); System.out.println("李四的商品:" + JedisUtils.smembers("package:2")); System.out.println("市场的商品:" + JedisUtils.zrangeWithScores("market:", 0, -1)); while (true) { // 监听商品是否被其余人买走了 Jedis jedis = JedisUtils.watch("market:"); double price = JedisUtils.zscore("market:", "itemX.1"); double funds = Double.valueOf(JedisUtils.hmget("person:2", "funds").get(0)); if (price > funds) { jedis.unwatch(); break; } Transaction transaction = jedis.multi(); // 张三的金额新增 transaction.hincrBy("person:1", "funds", new Double(price).longValue()); // 李四的金额减小 transaction.hincrBy("person:2", "funds", new Double(-price).longValue()); // 市场的商品移除 transaction.zrem("market:", "itemX.1"); // 李四的商品新增 transaction.sadd("package:2", "itemX"); List<Object> exec = transaction.exec(); // 不为空说明执行成功,跳出循环 if (null != exec) { break; } } System.out.println("张三的信息:" + JedisUtils.hgetAll("person:1")); System.out.println("李四的信息:" + JedisUtils.hgetAll("person:2")); System.out.println("李四的商品:" + JedisUtils.smembers("package:2")); System.out.println("市场的商品:" + JedisUtils.zrangeWithScores("market:", 0, -1)); }