jedis是一个著名的key-value存储系统,而作为其官方推荐的java版客户端jedis也非常强大和稳定,支持事务、管道及有jedis自身实现的分布式。

在这里对jedis关于事务、管道和分布式的调用方式做一个简单的介绍和对比:

一、普通同步方式

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

@Test

public 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的命令。

看下面例子:

@Test

public 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 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)

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

@Test

public 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 results = pipeline.syncAndReturnAll();

long end = System.currentTimeMillis();

System.out.println("Pipelined SET: " + ((end - start)/1000.0) + " seconds");

jedis.disconnect();

}

四、管道中调用事务

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

@Test

public 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 results = pipeline.syncAndReturnAll();

long end = System.currentTimeMillis();

System.out.println("Pipelined transaction: " + ((end - start)/1000.0) + " seconds");

jedis.disconnect();

}

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

五、分布式直连同步调用

@Test

public void test5shardNormal() {

List 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("

[email protected] SET: " + ((end - start)/1000.0) + " seconds");

sharding.disconnect();

}

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

六、分布式直连异步调用

@Test

public void test6shardpipelined() {

List 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 results = pipeline.syncAndReturnAll();

long end = System.currentTimeMillis();

System.out.println("

[email protected] SET: " + ((end - start)/1000.0) + " seconds");

sharding.disconnect();

}

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

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

@Test

public void test7shardSimplePool() {

List 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("

[email protected] SET: " + ((end - start)/1000.0) + " seconds");

pool.destroy();

}

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

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

@Test

public void test8shardPipelinedPool() {

List 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 results = pipeline.syncAndReturnAll();

long end = System.currentTimeMillis();

pool.returnResource(one);

System.out.println("

[email protected] SET: " + ((end - start)/1000.0) + " seconds");

pool.destroy();

}

九、需要注意的地方

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

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 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 results = pipeline.syncAndReturnAll();

事务和管道都是异步的,个人感觉,在管道中再进行事务调用,没有必要,不如直接进行事务模式。

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

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

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

十、测试

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

Simple SET: 5.227 seconds

Transaction SET: 0.5 seconds

Pipelined SET: 0.353 seconds

Pipelined transaction: 0.509 seconds

[email protected] SET: 5.289 seconds

[email protected] SET: 0.348 seconds

[email protected] SET: 5.039 seconds

[email protected] SET: 0.401 seconds

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

[email protected] SET: 5.494 seconds

[email protected] SET: 0.51 seconds

[email protected] SET: 5.223 seconds

[email protected] SET: 0.518 seconds

下面是10片:

[email protected] SET: 5.9 seconds

[email protected] SET: 0.794 seconds

[email protected] SET: 5.624 seconds

[email protected] SET: 0.762 seconds

下面是100片:

[email protected] SET: 14.055 seconds

[email protected] SET: 8.185 seconds

[email protected] SET: 13.29 seconds

[email protected] SET: 7.767 seconds

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

十一、完整的测试代码

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 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 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 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 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("

[email protected] 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 results = pipeline.syncAndReturnAll();

long end = System.currentTimeMillis();

System.out.println("

[email protected] 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("

[email protected] 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 results = pipeline.syncAndReturnAll();

long end = System.currentTimeMillis();

pool.returnResource(one);

System.out.println("

[email protected] SET: " + ((end - start)/1000.0) + " seconds");

}

}

转载请注明来源网站:www.itxm.cn谢谢!

分享到:

redis集群连接 java_Redis分布式集群和直连的Java客户端调用方式详解相关推荐

  1. mysql二进制方式_MySQL数据库之MySql二进制连接方式详解

    本文主要向大家介绍了MySQL数据库之MySql二进制连接方式详解 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. 使用mysql二进制方式连接 您可以使用MySQL二进制方式进 ...

  2. 交换机的连接方式详解(图)

    交换机的连接方式详解(图) http://www.xue5.com/itedu/200802/68974.html 交换机是一种最为基础的网络连接设备.它一般都不需要任何软件配置即可使用的一种纯硬件式 ...

  3. 集群和分布式的区别,软件架构的演化过程,Apache Dubbo详解

    集群和分布式的区别   集群是通过提高单位时间内执行的任务数来提升效率,分布式是以缩短单个任务的执行时间来提升效率的. 举个例子: &emsp: 例如: &emsp:  一个数据库里边 ...

  4. mysql集群 hbase_hbase完整分布式集群搭建

    简介: Hbase完成分布式安装步骤: 注意.hbase集群我是在前面的hadoop集群上继续搭建而来   (搭建好个节点后输入jps 各节点启动进程如下:) 主机 别名 安装软件 现有进程 服务地址 ...

  5. java站群系统_分布式站群系统设计与实现

    摘  要: 分析了高等院校构建网站时遇到的普遍问题,提出了文件分布存储.数据集中存储的设计思想,并且在Java EE平台上设计和实现了分布式站群管理系统,其站点分布式部署.高度的代码共享.内嵌的网页编 ...

  6. 蚁群算法(ACA)详细介绍(JAVA实现及代码详解)

    文章目录 1.蚁群算法概要 什么是蚁群算法 蚁群算法的数学公式 蚂蚁从i城市到j城市的概率公式 信息素的释放公式 信息素的挥发公式 蚁群算法的框架 2.TSP描述(旅行商问题) 3.JAVA源代码实现 ...

  7. 从分布式环境的特点、问题到CAP、BASE理论详解

    分布式的特点: 定义: 分布式系统是一个硬件或者软件组件分布在不同的网络计算机上,彼此之间仅仅通过网络进行通信和协调的系统. 特点: 同一个分布式系统中的计算机在空间部署上可以是任意分布的,这些计算机 ...

  8. 多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP

    在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式. 之前打算在sqlplus中用执行计划的,但是格式看起来有点乱,就用Toad 做了3个截图. 从3张图里我们看到了几点 ...

  9. Redis缓存穿透、缓存击穿、缓存雪崩及其多种处理方式详解

    文章目录 一.缓存穿透(数据查不到) 1.概念 2.解决方案 (1)解决方案一:缓存空对象 (2)解决方案二:布隆过滤器 二.缓存击穿(访问量太大,缓存正好过期) 1.概述 2.解决方案 (1)解决方 ...

最新文章

  1. 编译器设计-自下而上分析器-误差恢复-语义分析
  2. Azkaban的Web Server源码探究系列7: ExecutorManager的初始化
  3. HTTP Status 400 -
  4. C#:异步编程和线程的使用(.NET 4.5 ),异步方法改为同步执行
  5. 本地复现Zabbix v2.2.x, 3.0.0-3.0.3 jsrpc 参数 profileIdx2 SQL 注入漏洞
  6. wchar_t*,wchar_t,wchat_t数组,char,char*,char数组,std::string,std::wstring,CString....转换
  7. 欧几里德算法与扩展欧几里德算法
  8. mysql连接不上怎么重置密码错误_MySQL数据库连接不上、密码修改问题
  9. 下载离线aptana的eclipse插件
  10. Spring定时器@Scheduled
  11. 线性表的链式存储结构详解
  12. linux vi 表格,关于Linux vi命令 vi命令一览表
  13. 简谈五线制交流道岔控制电路故障的处理方法【铁路信号技术专栏】——转自微信公众号高速铁路信号技术交流
  14. 从身份证获取出生年月日
  15. STEP和IGES模型转换为适用Web的glb格式
  16. MySql命令行窗口操作
  17. 一个Android开发者眼中的微信小程序
  18. Python玩转数据分析——双因素方差分析
  19. 教你巧用后视镜判断车距
  20. 显示服务器事件,服务器事件查看

热门文章

  1. MySQL修改、删除表的结构
  2. linux文件目录含义,Linux中文件权限目录权限的意义及权限对文件目录的意义
  3. python中fd是什么意思_python里fd是什么意思
  4. python程序文件是什么_.py文件是什么?
  5. c/c++读取txt文件中指定行的内容_和尧名大叔一起从0开始学Python编程-简单读写文件
  6. linux下mysql5.7修改密码
  7. 二叉树---树的深度递归理解
  8. java 0xaarrggbb 转换_RRGGBBAA或者RRGGBB转换成rgba()
  9. emacs shell插件_Windows 下 Emacs 中的 zsh shell 使用方法
  10. 部署java项目_企业最看重什么样的Java人才?