Redis实战-chapter4

3 篇文章 0 订阅

事先说明:文章所使用的代码均为书籍赠送的代码,非本人写的。只是在上面做了点注解与解释

package redis;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Set;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.Tuple;

public class chapter4 {

	public static final void main(String[] args) {
		new chapter4().run();
	}
	public void run()
	{
		Jedis conn = new Jedis("localhost");
		conn.select(15);
		
		testListItem(conn,false);
		testPurchaseItem(conn);
        testBenchmarkUpdateToken(conn);
	}
	public void testListItem(Jedis conn,boolean nested)
	{
		if(!nested)
			System.out.println("\n1.0----- testListItem -----");
		
		System.out.println("1.1We need to set up just enough state so that a user can list an item");
        String seller = "userX";
        //商品名称
        String item = "itemX";
        //set在inventory:seller内添加商品名称
        conn.sadd("inventory:"+seller,item);
        Set<String> iSet = conn.smembers("inventory:"+seller);
        System.out.println("The user's inventory has:");
        for (String member : iSet){
            System.out.println("  " + member);
        }
        System.out.println();

        System.out.println("1.2Listing the item...");
        boolean l = listItem(conn, item, seller, 10);
        System.out.println("1.3Listing the item succeeded? " + l);
        assert l;
        //zset从market:中按照从小到达的顺序读取元素
        Set<Tuple> r = conn.zrangeWithScores("market:", 0, -1);
        System.out.println("The market contains:");
        for (Tuple tuple : r){
            System.out.println("  " + tuple.getElement() + ", " + tuple.getScore());
        }
        assert r.size() > 0;
	}
	public void testPurchaseItem(Jedis conn)
	{
		System.out.println("\n----- testPurchaseItem -----");
        testListItem(conn, true);
        System.out.println("We need to set up just enough state so a user can buy an item");
        //hash从users:userY中添加{funds[String],value[String]}
        conn.hset("users:userY", "funds", "125");
        //hash从users:userY中获取其所有的信息{[name,nameAbc],[funds,value]}
        Map<String,String> r = conn.hgetAll("users:userY");
        System.out.println("The user has some money:");
        for (Map.Entry<String,String> entry : r.entrySet()){
            System.out.println("  " + entry.getKey() + ": " + entry.getValue());
        }
        assert r.size() > 0;
        assert r.get("funds") != null;
        System.out.println();

        System.out.println("Let's purchase an item");
        boolean p = purchaseItem(conn, "userY", "itemX", "userX", 10);
        System.out.println("Purchasing an item succeeded? " + p);
        assert p;
        r = conn.hgetAll("users:userY");
        System.out.println("Their money is now:");
        for (Map.Entry<String,String> entry : r.entrySet()){
            System.out.println("  " + entry.getKey() + ": " + entry.getValue());
        }
        assert r.size() > 0;

        String buyer = "userY";
        Set<String> i = conn.smembers("inventory:" + buyer);
        System.out.println("Their inventory is now:");
        for (String member : i){
            System.out.println("  " + member);
        }
        assert i.size() > 0;
        assert i.contains("itemX");
        assert conn.zscore("market:", "itemX.userX") == null;
	}
	public void testBenchmarkUpdateToken(Jedis conn)
	{
		System.out.println("\n----- testBenchmarkUpdate -----");
        benchmarkUpdateToken(conn, 5);
	}
	public boolean listItem(Jedis conn,String itemId,String sellerId,double price)
	{
		String inventory = "inventory:"+sellerId;
		String item = itemId+"."+sellerId;
		long end = System.currentTimeMillis()+5000;
		while(System.currentTimeMillis()<end){
			//开启监视用户包裹的变化
			conn.watch(inventory);
			//如果卖家包裹中的商品不存在的话,则返回false
			if(!conn.sismember(inventory, itemId)){
				//关闭监视
				conn.unwatch();
				return false;
			}
			//开启事务,表示这里的事务是不可打扰的
			Transaction transaction = conn.multi();
			//zset在market:中添加{item[String],price[double]}
			transaction.zadd("market:",price,item);
			//set删除inventory:seller中的itemId(商品名称)
			transaction.srem(inventory,itemId);
			List<Object> result = transaction.exec();
			if(result == null){
				continue;
			}
			return true;
		}
		return false;
	}
	public boolean purchaseItem(Jedis conn,String buyerId,String itemId,String sellerId,double lprice)
	{
		String buyer = "users:" + buyerId;
        String seller = "users:" + sellerId;
        String item = itemId + '.' + sellerId;
        String inventory = "inventory:" + buyerId;
        long end = System.currentTimeMillis()+10000;
        
        while(System.currentTimeMillis()<end){
        	conn.watch("market:",buyer);
        	//zset按照market:中的商品名称{itemA.Id}获取价格
        	double price = conn.zscore("market:", item);
        	//hash获取购买者的余额是否足够
            double funds = Double.parseDouble(conn.hget(buyer, "funds"));
            //如果价格改变了,或者售价高于余额则返回false
            if (price != lprice || price > funds){
                conn.unwatch();
                return false;
            }
            //开启事务
            Transaction trans = conn.multi();
            //hash进行买家和卖家之间的钱交易
            trans.hincrBy(seller, "funds", (int)price);
            trans.hincrBy(buyer, "funds", (int)-price);
            //set通过inventory:userId添加用户从库内的物品
            trans.sadd(inventory, itemId);
            //zset通过market:内删除item商品信息
            trans.zrem("market:", item);
            //事务执行
            List<Object> results = trans.exec();
            // null response indicates that the transaction was aborted due to
            // the watched key changing.
            if (results == null){
                continue;
            }
            return true;
        }
        
        return true;
        
	}
	public void benchmarkUpdateToken(Jedis conn,int duration)
	{
		try{
            @SuppressWarnings("rawtypes")
            Class[] args = new Class[]{
                Jedis.class, String.class, String.class, String.class};
            Method[] methods = new Method[]{
                this.getClass().getDeclaredMethod("updateToken", args),
                this.getClass().getDeclaredMethod("updateTokenPipeline", args),
            };
            for (Method method : methods){
                int count = 0;
                long start = System.currentTimeMillis();
                long end = start + (duration * 1000);
                while (System.currentTimeMillis() < end){
                    count++;
                    method.invoke(this, conn, "token", "user", "item");
                }
                long delta = System.currentTimeMillis() - start;
                System.out.println(
                        method.getName() + ' ' +
                        count + ' ' +
                        (delta / 1000) + ' ' +
                        (count / (delta / 1000)));
            }
        }catch(Exception e){
            throw new RuntimeException(e);
        }
	}
	//该函数是使用流水线的pipelined(true/null)
	public void updateToken(Jedis conn, String token, String user, String item) {
        long timestamp = System.currentTimeMillis() / 1000;
        conn.hset("login:", token, user);
        conn.zadd("recent:", timestamp, token);
        if (item != null) {
            conn.zadd("viewed:" + token, timestamp, item);
            conn.zremrangeByRank("viewed:" + token, 0, -26);
            conn.zincrby("viewed:", -1, item);
        }
    }

	//该函数是不使用流水线的pipelined(false)
    public void updateTokenPipeline(Jedis conn, String token, String user, String item) {
        long timestamp = System.currentTimeMillis() / 1000;
        Pipeline pipe = conn.pipelined();
        pipe.multi();
        pipe.hset("login:", token, user);
        pipe.zadd("recent:", timestamp, token);
        if (item != null){
            pipe.zadd("viewed:" + token, timestamp, item);
            pipe.zremrangeByRank("viewed:" + token, 0, -26);
            pipe.zincrby("viewed:", -1, item);
        }
        pipe.exec();
    }

}

 运行结果:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值