一、结构设计
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;
}