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

fff6c98081bf8904098fb5e1bd59ff4b.gif

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");

}

}

fff6c98081bf8904098fb5e1bd59ff4b.gif

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

分享到:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/572800.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【bzoj1705】[Usaco2007 Nov]Telephone Wire 架设电话线 dp

题目描述 最近&#xff0c;Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是&#xff0c;她们要求FJ把那些老旧的电话线换成性能更好的新电话线。 新的电话线架设在已有的N(2 < N < 100,000)根电话线杆上&#xff0c; 第i根电话线杆的高度为height_i米(1 &…

Loadrunner进行HTTPS协议性能测试

1.最简单办法就是在脚本前面加上&#xff1a;web_set_sockets_option("SSL_VERSION","TLS")&#xff0c;一般能解决HTTPS协议的请求问题&#xff0c;无毒无公害&#xff0c;快速还能解决问题 2.其实对于HTTP跟HTTPS&#xff0c;只是在服务器端配置到底是走…

Linux 权限、磁盘操作命令-Linux基础环境命令学习笔记

1、创建用户和用户组 1&#xff09;用户和用户组 /etc/passwd  保存系统用户的基本信息 /etc/group    保存用户组信息 用户名&#xff1a;x&#xff1a;UID&#xff1a;GID 2&#xff09;基本命令 useradd  增加用户 groupadd  增加用户组 passwd  为用户设置密码…

java伪代码生成器_JAVA单例模式的实现伪代码

什么是单例&#xff1f;&#xff1a;其定义是单例对象的类只能允许一个实例存在单例的实现基本原理&#xff1a;1.将该类的构造方法定义为私有访问&#xff0c;不对外暴露从而使其他类不能实例化该类对象&#xff0c;只能通过该类的静态方法得到该类的唯一实例 2.在该类中定义一…

python怎么存储数据_Python:如何在类中存储数据并继承

我对课程很陌生,我已经写了一个班来做熊猫的操作。分类方法,但我不知道如何使用它们。我的班级目标:我想写一个权限类。它应该加载/写入一个json文件,并且应该能够添加更多的权限。编辑:读了一段时间后,我发现staticmethod还有一个__init__在初始化期间加载文件的。class Permi…

Eclipse手动配置svn

1、在Eclipse根目录下建一个任意文件夹&#xff08;如plugin&#xff09;&#xff0c;在该文件夹下建一个以该插件名命名的文件夹&#xff08;如SVN&#xff09;。2、将下载下的插件文件解压&#xff0c;plugins和features文件夹复制到该文件夹下&#xff08;SVN&#xff09;。…

java爬虫新浪微博_java爬虫(爬新浪新闻) 如何从零开始

爬虫通常搜索引擎处理的对象是互联网网页。首先面临的问题是&#xff1a;如何能够设计出高效的下载系统&#xff0c;以将如此海量的网页数据传送到本地&#xff0c;在本地形成互联网网页的镜像备份。网络爬虫即起此作用&#xff0c;它是搜索引擎系统中很关键也很基础的构件。爬…

Hibernate Query 的 list 和iterate方法缓存的区别

list: quert.list()方法会将从数据库查找到的数据库放到一级缓存和二级缓存,但是不能从一级和二级缓存读取数据,但是可以从二级缓存的查询缓存读取数据, iterate: quert.iterate()方法总会先查找数据表的主键,然后根据每一个主键发送对应的sql语句从数据库读取数据,它可以把数据…

java的type转化class_第七章 (类型转换)Type Convertion

第七章 Type Convertion为什么会有类型转换&#xff1f;HTTP协议中传递的任何内容都是String类型的&#xff0c;所以一旦我们在服务器上需要一个非String类型的对象&#xff0c;例如&#xff1a;int或者Date&#xff0c;那么我们就需要在收到HTTP请求的数据的时候&#xff0c;首…

CodeVS 1068-乌龟棋

原题 题目描述 Description 小明过生日的时候&#xff0c;爸爸送给他一副乌龟棋当作礼物。 乌龟棋的棋盘是一行N个格子&#xff0c;每个格子上一个分数&#xff08;非负整数&#xff09;。棋盘第1格是唯一 的起点&#xff0c;第N格是终点&#xff0c;游戏要求玩家控制一个乌龟棋…

java游戏暂停弹出字体_小白写了个java的小游戏 想加个暂停的功能 无从下手 求大佬们帮...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼第一次写java的小游戏想实现点击右下角的暂停 实现游戏的暂停和继续 不知道该怎么加&#xff0c;自己找了线程的内容但试了还是成功不了&#xff0c;求大佬们帮一下小白。代码有点乱&#xff0c;大佬们见谅。&#xff0c;&#xff…

乔布斯传

资料参考 http://www.ruanyifeng.com/blog/2013/03/apple_inc_and_division_of_labor.html 苹果公司与分工原理 1.乔布斯 "乔布斯买了一间不错的房子&#xff0c;但家里只有一幅帕黎思&#xff08;Maxfield Parrish&#xff09;的画作、一部百灵牌咖啡机和几把双人牌的刀子…

JAVA5000行代码什么概念_GitHub - catstiger/mvc: 一个不超过5000行代码的,快速,简单,易用的MVC框架。...

一个不超过5000行代码的&#xff0c;快速&#xff0c;简单&#xff0c;易用的MVC框架。我们的目的是&#xff1a;让MVC回归其最初的目的。因简单而快速&#xff0c;超过目前各种主流MVC。零侵入&#xff0c;零配置&#xff0c;易于测试&#xff0c;并且让开发者感觉不到MVC的存…

33 Java语言基础控制跳转语句标号

1 public class Add9 {2 public static void main(String[] args) {3 4 a:for (int i 1; i <9 ; i) { // 标号为合法的标识符5 System.out.println("\n");6 b:for (int j 1; j <i ; j) {7 8 System.o…

java 配置jmstemplate_Spring JMSTemplate 与 JMS 原生API比较

JMSUtil与Spring JmsTemplate的对比Author&#xff1a;信仰Date&#xff1a;2012-4-20未完待续&#xff0c;截止日期2012-4-20从以下几方面比较JMSUtil和Spring JmsTemplatel 对JNDI的支持l 对ConnectionFactory、Connection、Destination、Session、MessageProducer、Messag…

java微信支付必要参数_微信支付 开发账号体系各参数详解

商户在微信公众平台提交申请资料以及银行账户资料&#xff0c;资料审核通过并签约后&#xff0c;可以获得表6-4所示帐户(包含财付通的相关支付资金账户)&#xff0c;用于公众帐号支付。帐号及作用&#xff1a;appid &#xff1a;公众帐号身份的唯一标识。审核通过后&#xff0c…

MyEclipse10的正确破解方法

无法转载&#xff0c;故给出原文链接&#xff0c;以供需要者。 MyEclipse10的正确破解方法转载于:https://www.cnblogs.com/qbzf-Blog/p/6341400.html

【二分法】- leetcode

275. H-Index II 278. First Bad Version 此题的条件必须是left < right, 否则如果只有一个版本的话&#xff0c;一直跳不出循环&#xff0c; time limitation。转载于:https://www.cnblogs.com/93scarlett/p/6353765.html

mysql referential_constraints_hibernate4.3.8与spring mvc结合遇到的问题

2703 [2015-01-21 16:47:42 ] - [ip, ref, ua, sid]WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 1109, SQLState: 42S022703 [2015-01-21 16:47:42 ] - [ip, ref, ua, sid]ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Unknown table ‘referential_constraints‘ in …

ie11浏览器可以下载java吗_解析:WindowsXP系统能否安装IE11浏览器

现在&#xff0c;IE浏览器可以称得上是市场占有率最高的一款网页浏览器。因为windowsxp是一款比较久的操作系统&#xff0c;所以很多用户都会疑惑在xp上是否能够安装最新版的ie11浏览器。下面&#xff0c;小编就给大家详细解答下该问题。很遗憾的告诉大家&#xff0c;Windows X…