Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式)介绍

来源:互联网 发布:消费者数据库 编辑:程序博客网 时间:2024/06/05 18:18
在这里对jedis关于事务、管道和分布式的调用方式做一个简单的介绍和对比:

一、普通同步方式

最简单和基础的调用方式,

@Testpublic void test1Normal() {    Jedis jedis = new Jedis("localhost");    long start = System.currentTimeMillis();    for (int i = 0; i < 100000; i++) {        String result = jedis.set("n" + i, "n" + i);    }    long end = System.currentTimeMillis();    System.out.println("Simple SET: " + ((end - start)/1000.0) + " seconds");    jedis.disconnect();}

很简单吧,每次set之后都可以返回结果,标记是否成功。

二、事务方式(Transactions)

redis的事务很简单,他主要目的是保障,一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。

看下面例子:

@Testpublic void test2Trans() {    Jedis jedis = new Jedis("localhost");    long start = System.currentTimeMillis();    Transaction tx = jedis.multi();    for (int i = 0; i < 100000; i++) {        tx.set("t" + i, "t" + i);    }    List<Object> results = tx.exec();    long end = System.currentTimeMillis();    System.out.println("Transaction SET: " + ((end - start)/1000.0) + " seconds");    jedis.disconnect();}

我们调用jedis.watch(…)方法来监控key,如果调用后key值发生变化,则整个事务会执行失败。另外,事务中某个操作失败,并不会回滚其他操作。这一点需要注意。还有,我们可以使用discard()方法来取消事务。

三、管道(Pipelining)

有时,我们需要采用异步方式,一次发送多个指令,不同步等待其返回结果。这样可以取得非常好的执行效率。这就是管道,调用方法如下:

@Testpublic void test3Pipelined() {    Jedis jedis = new Jedis("localhost");    Pipeline pipeline = jedis.pipelined();    long start = System.currentTimeMillis();    for (int i = 0; i < 100000; i++) {        pipeline.set("p" + i, "p" + i);    }    List<Object> results = pipeline.syncAndReturnAll();    long end = System.currentTimeMillis();    System.out.println("Pipelined SET: " + ((end - start)/1000.0) + " seconds");    jedis.disconnect();}

四、管道中调用事务

就Jedis提供的方法而言,是可以做到在管道中使用事务,其代码如下:

@Testpublic void test4combPipelineTrans() {    jedis = new Jedis("localhost");     long start = System.currentTimeMillis();    Pipeline pipeline = jedis.pipelined();    pipeline.multi();    for (int i = 0; i < 100000; i++) {        pipeline.set("" + i, "" + i);    }    pipeline.exec();    List<Object> results = pipeline.syncAndReturnAll();    long end = System.currentTimeMillis();    System.out.println("Pipelined transaction: " + ((end - start)/1000.0) + " seconds");    jedis.disconnect();}

但是经测试(见本文后续部分),发现其效率和单独使用事务差不多,甚至还略微差点。

五、分布式直连同步调用

@Testpublic void test5shardNormal() {    List<JedisShardInfo> shards = Arrays.asList(            new JedisShardInfo("localhost",6379),            new JedisShardInfo("localhost",6380));    ShardedJedis sharding = new ShardedJedis(shards);    long start = System.currentTimeMillis();    for (int i = 0; i < 100000; i++) {        String result = sharding.set("sn" + i, "n" + i);    }    long end = System.currentTimeMillis();    System.out.println("Simple@Sharing SET: " + ((end - start)/1000.0) + " seconds");    sharding.disconnect();}

这个是分布式直接连接,并且是同步调用,每步执行都返回执行结果。类似地,还有异步管道调用。

六、分布式直连异步调用

@Testpublic void test6shardpipelined() {    List<JedisShardInfo> shards = Arrays.asList(            new JedisShardInfo("localhost",6379),            new JedisShardInfo("localhost",6380));    ShardedJedis sharding = new ShardedJedis(shards);    ShardedJedisPipeline pipeline = sharding.pipelined();    long start = System.currentTimeMillis();    for (int i = 0; i < 100000; i++) {        pipeline.set("sp" + i, "p" + i);    }    List<Object> results = pipeline.syncAndReturnAll();    long end = System.currentTimeMillis();    System.out.println("Pipelined@Sharing SET: " + ((end - start)/1000.0) + " seconds");    sharding.disconnect();}

七、分布式连接池同步调用

如果,你的分布式调用代码是运行在线程中,那么上面两个直连调用方式就不合适了,因为直连方式是非线程安全的,这个时候,你就必须选择连接池调用。

@Testpublic void test7shardSimplePool() {    List<JedisShardInfo> shards = Arrays.asList(            new JedisShardInfo("localhost",6379),            new JedisShardInfo("localhost",6380));    ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);    ShardedJedis one = pool.getResource();    long start = System.currentTimeMillis();    for (int i = 0; i < 100000; i++) {        String result = one.set("spn" + i, "n" + i);    }    long end = System.currentTimeMillis();    pool.returnResource(one);    System.out.println("Simple@Pool SET: " + ((end - start)/1000.0) + " seconds");    pool.destroy();}

上面是同步方式,当然还有异步方式。

八、分布式连接池异步调用

@Testpublic void test8shardPipelinedPool() {    List<JedisShardInfo> shards = Arrays.asList(            new JedisShardInfo("localhost",6379),            new JedisShardInfo("localhost",6380));    ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);    ShardedJedis one = pool.getResource();    ShardedJedisPipeline pipeline = one.pipelined();    long start = System.currentTimeMillis();    for (int i = 0; i < 100000; i++) {        pipeline.set("sppn" + i, "n" + i);    }    List<Object> results = pipeline.syncAndReturnAll();    long end = System.currentTimeMillis();    pool.returnResource(one);    System.out.println("Pipelined@Pool SET: " + ((end - start)/1000.0) + " seconds");    pool.destroy();}

九、需要注意的地方

  1. 事务和管道都是异步模式。在事务和管道中不能同步查询结果。比如下面两个调用,都是不允许的:

     Transaction tx = jedis.multi(); for (int i = 0; i < 100000; i++) {     tx.set("t" + i, "t" + i); } System.out.println(tx.get("t1000").get());  //不允许 List<Object> results = tx.exec(); … … Pipeline pipeline = jedis.pipelined(); long start = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) {     pipeline.set("p" + i, "p" + i); } System.out.println(pipeline.get("p1000").get()); //不允许 List<Object> results = pipeline.syncAndReturnAll();
  2. 事务和管道都是异步的,个人感觉,在管道中再进行事务调用,没有必要,不如直接进行事务模式。

  3. 分布式中,连接池的性能比直连的性能略好(见后续测试部分)。

  4. 分布式调用中不支持事务。

    因为事务是在服务器端实现,而在分布式中,每批次的调用对象都可能访问不同的机器,所以,没法进行事务。

十、测试

运行上面的代码,进行测试,其结果如下:

Simple SET: 5.227 secondsTransaction SET: 0.5 secondsPipelined SET: 0.353 secondsPipelined transaction: 0.509 secondsSimple@Sharing SET: 5.289 secondsPipelined@Sharing SET: 0.348 secondsSimple@Pool SET: 5.039 secondsPipelined@Pool SET: 0.401 seconds

另外,经测试分布式中用到的机器越多,调用会越慢。上面是2片,下面是5片:

Simple@Sharing SET: 5.494 secondsPipelined@Sharing SET: 0.51 secondsSimple@Pool SET: 5.223 secondsPipelined@Pool SET: 0.518 seconds

下面是10片:

Simple@Sharing SET: 5.9 secondsPipelined@Sharing SET: 0.794 secondsSimple@Pool SET: 5.624 secondsPipelined@Pool SET: 0.762 seconds

下面是100片:

Simple@Sharing SET: 14.055 secondsPipelined@Sharing SET: 8.185 secondsSimple@Pool SET: 13.29 secondsPipelined@Pool SET: 7.767 seconds

分布式中,连接池方式调用不但线程安全外,根据上面的测试数据,也可以看出连接池比直连的效率更好。

十一、完整的测试代码

package com.example.nosqlclient;import java.util.Arrays;import java.util.List;import org.junit.AfterClass;import org.junit.BeforeClass;import org.junit.Test;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPoolConfig;import redis.clients.jedis.JedisShardInfo;import redis.clients.jedis.Pipeline;import redis.clients.jedis.ShardedJedis;import redis.clients.jedis.ShardedJedisPipeline;import redis.clients.jedis.ShardedJedisPool;import redis.clients.jedis.Transaction;import org.junit.FixMethodOrder;import org.junit.runners.MethodSorters;@FixMethodOrder(MethodSorters.NAME_ASCENDING)public class TestJedis {    private static Jedis jedis;    private static ShardedJedis sharding;    private static ShardedJedisPool pool;    @BeforeClass    public static void setUpBeforeClass() throws Exception {        List<JedisShardInfo> shards = Arrays.asList(                new JedisShardInfo("localhost",6379),                new JedisShardInfo("localhost",6379)); //使用相同的ip:port,仅作测试        jedis = new Jedis("localhost");         sharding = new ShardedJedis(shards);        pool = new ShardedJedisPool(new JedisPoolConfig(), shards);    }    @AfterClass    public static void tearDownAfterClass() throws Exception {        jedis.disconnect();        sharding.disconnect();        pool.destroy();    }    @Test    public void test1Normal() {        long start = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            String result = jedis.set("n" + i, "n" + i);        }        long end = System.currentTimeMillis();        System.out.println("Simple SET: " + ((end - start)/1000.0) + " seconds");    }    @Test    public void test2Trans() {        long start = System.currentTimeMillis();        Transaction tx = jedis.multi();        for (int i = 0; i < 100000; i++) {            tx.set("t" + i, "t" + i);        }        //System.out.println(tx.get("t1000").get());        List<Object> results = tx.exec();        long end = System.currentTimeMillis();        System.out.println("Transaction SET: " + ((end - start)/1000.0) + " seconds");    }    @Test    public void test3Pipelined() {        Pipeline pipeline = jedis.pipelined();        long start = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            pipeline.set("p" + i, "p" + i);        }        //System.out.println(pipeline.get("p1000").get());        List<Object> results = pipeline.syncAndReturnAll();        long end = System.currentTimeMillis();        System.out.println("Pipelined SET: " + ((end - start)/1000.0) + " seconds");    }    @Test    public void test4combPipelineTrans() {        long start = System.currentTimeMillis();        Pipeline pipeline = jedis.pipelined();        pipeline.multi();        for (int i = 0; i < 100000; i++) {            pipeline.set("" + i, "" + i);        }        pipeline.exec();        List<Object> results = pipeline.syncAndReturnAll();        long end = System.currentTimeMillis();        System.out.println("Pipelined transaction: " + ((end - start)/1000.0) + " seconds");    }    @Test    public void test5shardNormal() {        long start = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            String result = sharding.set("sn" + i, "n" + i);        }        long end = System.currentTimeMillis();        System.out.println("Simple@Sharing SET: " + ((end - start)/1000.0) + " seconds");    }    @Test    public void test6shardpipelined() {        ShardedJedisPipeline pipeline = sharding.pipelined();        long start = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            pipeline.set("sp" + i, "p" + i);        }        List<Object> results = pipeline.syncAndReturnAll();        long end = System.currentTimeMillis();        System.out.println("Pipelined@Sharing SET: " + ((end - start)/1000.0) + " seconds");    }    @Test    public void test7shardSimplePool() {        ShardedJedis one = pool.getResource();        long start = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            String result = one.set("spn" + i, "n" + i);        }        long end = System.currentTimeMillis();        pool.returnResource(one);        System.out.println("Simple@Pool SET: " + ((end - start)/1000.0) + " seconds");    }    @Test    public void test8shardPipelinedPool() {        ShardedJedis one = pool.getResource();        ShardedJedisPipeline pipeline = one.pipelined();        long start = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            pipeline.set("sppn" + i, "n" + i);        }        List<Object> results = pipeline.syncAndReturnAll();        long end = System.currentTimeMillis();        pool.returnResource(one);        System.out.println("Pipelined@Pool SET: " + ((end - start)/1000.0) + " seconds");    }}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 主动退市股票钱怎么办 老板卷款逃跑财务怎么办 房开延迟交房怎么办 房开逾期交房怎么办 买了保险想退保怎么办 辐射避难所探索废土死了怎么办 大门上边的齿轮滑丝怎么办 国通石油储油卡怎么办 买大棚房受骗了怎么办 朋友做安利天天来我门面怎么办 安利优惠顾客卡怎么办 苹果手机天气温度不显示怎么办? 安利净水器坏了怎么办 安利净水器滤芯盖搭配坏怎么办 安利会员卡过期了怎么办 婴儿吃了润唇膏怎么办? 用错沐浴露洗头怎么办 雅蜜润肤沐浴露怎么办 自煮小火锅水放少了怎么办 安利皇后锅发黑怎么办 宝宝灌肠后不拉屎怎么办 吃蛋白质粉肚子长胖了怎么办 安利产品过期了怎么办 拼多多拼不到人怎么办 被海南大宗骗了怎么办 手机被游戏扣钱怎么办 做酵素剩下的水果怎么办 喝了酵素胃疼怎么办 海科融通不到账怎么办 美团外卖没生意怎么办 淘宝联盟领券销售怎么办 微信返利被骗了怎么办 众筹失败后资金怎么办 健身房不给退卡怎么办 婆婆陷入民间传销组织怎么办 被三生公司骗了怎么办? ppt保存成了图片怎么办 苹果6速度变慢了怎么办 苹果6s速度很慢怎么办 微信支付上限了怎么办 佳享健康骗老人怎么办