redis-實現商品交易

一、結構設計

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;
	}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章