參考《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)); }