一、結構設計
1、需要設計用戶存儲結構hash,來存放當前用戶具有的金錢數
2、設計用戶包裹set,裏邊存儲了用戶的所有商品
3、設計交易區market:zset集合來存儲,存儲格式爲item.user price
用戶流程:
1、將自己擁有的商品放置到貿易區,並設定一定的價格,在放置過程中需要去查看當前商品是否有變動,因爲redis採用的是樂觀鎖
2、用戶去交易區購買商品,首先去查看自身是否具有足夠的錢去購買商品,一旦能夠購買該商品,此時就去要需要修改購買者的錢數、修改出售者的錢數、交易區商品刪除、購買者包裹添加該商品
二、用戶掛賣商品
1、markets:表示交易區
2、inventory:表示自身包裹
// 查看商品列表
public static boolean ListItem(Jedis jedis, String itemID, String sellerId, float price) {
String inventory = "inventory:" + sellerId;
String item = itemID + "." + sellerId;
long end = System.currentTimeMillis() / 1000 + 5;
while (System.currentTimeMillis() / 1000 < end) {
jedis.watch(inventory);
if (!jedis.sismember(inventory, itemID)) {
jedis.unwatch();
return false;
}
Transaction trans = jedis.multi();
trans.zadd("markets:", price, item);
trans.srem(inventory, itemID);
List<Object> list = trans.exec();
if (list == null) {
continue;
}
}
return true;
}
三、購買商品
1、funds:hash結構中用戶的錢數
2、商品在交易區結構:itemID .SellerID price
public boolean purchase(Jedis jedis, String buyerID, String SellerID, String itemID) {
String buyer = "user:" + buyerID;
String seller = "user:" + SellerID;
String item = itemID + "." + SellerID;
String inventory = "inventory:" + buyerID;
long time = System.currentTimeMillis() / 1000 + 10;
while (System.currentTimeMillis() / 1000 < time) {
jedis.watch(buyer);
double buyerMoney = Double.parseDouble(jedis.hget(buyer, "funds"));
double price = jedis.zscore("markets:", item);
if (buyerMoney < price) {
jedis.unwatch();
return false;
}
Transaction trans = jedis.multi();
trans.hincrBy(buyer, "funds", (int)-price);// 花錢
trans.hincrBy(seller, "funds", (int)price);
trans.sadd(inventory, itemID);// 添加商品
trans.zrem("markets:", item);// 交易市場去掉該商品
List<Object> list = trans.exec();
if (list == null) {
continue;
}
return true;
}
return false;
}
四、test
private void testPurse(Jedis jedis) {
jedis.hset("user:userY", "funds", "250");
Map<String, String> map = jedis.hgetAll("user:userY");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
assert map.size() > 0;
boolean b = purchase(jedis, "userY", "userX", "ItemX");
Set<String> set = jedis.smembers("inventory:userY");
for (String temp : set) {
System.out.println("購買商品:" + temp);
}
assert set.size() > 0;
System.out.println("用戶當前錢數");
map = jedis.hgetAll("user:userY");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
assert set.contains("ItemX");
assert jedis.zscore("markets:", "itemX:userX") == null;
}
public void tesList(Jedis jedis) {
String ItemID = "ItemX";
String sellerID = "userX";
System.out.println("添加商品");
jedis.sadd("inventory:" + sellerID, ItemID);
Set<String> set = jedis.smembers("inventory:" + sellerID);
for (String temp : set) {
System.out.println(temp);
}
assert set.size() > 0;
System.out.println("將商品放置到交易區");
ListItem(jedis, ItemID, sellerID, 10);
Set<Tuple> tuples = jedis.zrangeWithScores("markets:", 0, -1);
for (Tuple tuple : tuples) {
System.out.println(tuple.getElement() + "-" + tuple.getScore());
}
assert tuples.size() > 0;
}