Jedis使用教程完整版
2019独角兽企业重金招聘Python工程师标准>>>
- 摘要:概述Jedis是Redis官方推荐的Java连接开发工具。要在Java开发中使用好Redis中间件,必须对Jedis熟悉才能写成漂亮的代码。这篇文章不描述怎么安装Redis和Reids的命令,只对Jedis的使用进行对介绍。1.基本使用Jedis的基本使用非常简单,只需要创建Jedis对象的时候指定host,port,password即可。当然,Jedis对象又很多构造方法,都大同小异,只是对应和Redis连接的socket的参数不一样而已。Jedisjedis=newJed
- 概述
Jedis是Redis官方推荐的Java连接开发工具。要在Java开发中使用好Redis中间件,必须对Jedis熟悉才能写成漂亮的代码。这篇文章不描述怎么安装Redis和Reids的命令,只对Jedis的使用进行对介绍。
1. 基本使用
Jedis的基本使用非常简单,只需要创建Jedis对象的时候指定host,port, password即可。当然,Jedis对象又很多构造方法,都大同小异,只是对应和Redis连接的socket的参数不一样而已。
Jedis jedis = new Jedis("localhost", 6379);//指定Redis服务Host和port
jedis.auth("xxxx"); //如果Redis服务连接需要密码,制定密码
String value = jedis.get("key"); //访问Redis服务
jedis.close(); //使用完关闭连接Jedis基本使用十分简单,在每次使用时,构建Jedis对象即可。在Jedis对象构建好之后,Jedis底层会打开一条Socket通道和Redis服务进行连接。所以在使用完Jedis对象之后,需要调用Jedis.close()方法把连接关闭,不如会占用系统资源。当然,如果应用非常平凡的创建和销毁Jedis对象,对应用的性能是很大影响的,因为构建Socket的通道是很耗时的(类似数据库连接)。我们应该使用连接池来减少Socket对象的创建和销毁过程。
2. 连接池使用
Jedis连接池是基于apache-commons pool2实现的。在构建连接池对象的时候,需要提供池对象的配置对象,及JedisPoolConfig(继承自GenericObjectPoolConfig)。我们可以通过这个配置对象对连接池进行相关参数的配置(如最大连接数,最大空数等)。
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(8);
config.setMaxTotal(18);
JedisPool pool = new JedisPool(config, "127.0.0.1", 6379, 2000, "password");
Jedis jedis = pool.getResource();
String value = jedis.get("key");
......
jedis.close();
pool.close();使用Jedis连接池之后,在每次用完连接对象后一定要记得把连接归还给连接池。Jedis对close方法进行了改造,如果是连接池中的连接对象,调用Close方法将会是把连接对象返回到对象池,若不是则关闭连接。可以查看如下代码
@Override
public void close() { //Jedis的close方法
if (dataSource != null) {
if (client.isBroken()) {
this.dataSource.returnBrokenResource(this);
} else {
this.dataSource.returnResource(this);
}
} else {
client.close();
}
}
//另外从对象池中获取Jedis链接时,将会对dataSource进行设置
// JedisPool.getResource()方法
public Jedis getResource() {
Jedis jedis = super.getResource();
jedis.setDataSource(this);
return jedis;
}
3. 高可用连接我们知道,连接池可以大大提高应用访问Reids服务的性能,减去大量的Socket的创建和销毁过程。但是Redis为了保障高可用,服务一般都是Sentinel部署方式(可以查看我的文章详细了解)。当Redis服务中的主服务挂掉之后,会仲裁出另外一台Slaves服务充当Master。这个时候,我们的应用即使使用了Jedis连接池,Master服务挂了,我们的应用奖还是无法连接新的Master服务。为了解决这个问题,Jedis也提供了相应的Sentinel实现,能够在Redis Sentinel主从切换时候,通知我们的应用,把我们的应用连接到新的 Master服务。先看下怎么使用。
注意:Jedis版本必须2.4.2或更新版本
Set sentinels = new HashSet<>();
sentinels.add("172.18.18.207:26379");
sentinels.add("172.18.18.208:26379");
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(5);
config.setMaxTotal(20);
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, config);
Jedis jedis = pool.getResource();
jedis.set("jedis", "jedis");
......
jedis.close();
pool.close();Jedis Sentinel的使用也是十分简单的,只是在JedisPool中添加了Sentinel和MasterName参数。Jedis Sentinel底层基于Redis订阅实现Redis主从服务的切换通知。当Reids发生主从切换时,Sentinel会发送通知主动通知Jedis进行连接的切换。JedisSentinelPool在每次从连接池中获取链接对象的时候,都要对连接对象进行检测,如果此链接和Sentinel的Master服务连接参数不一致,则会关闭此连接,重新获取新的Jedis连接对象。
public Jedis getResource() {
while (true) {
Jedis jedis = super.getResource();
jedis.setDataSource(this);
// get a reference because it can change concurrently
final HostAndPort master = currentHostMaster;
final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(), jedis.getClient().getPort());
if (master.equals(connection)) {
// connected to the correct master
return jedis;
} else {
returnBrokenResource(jedis);
}
}
}当然,JedisSentinelPool对象要时时监控RedisSentinel的主从切换。在其内部通过Reids的订阅实现。具体的实现看JedisSentinelPool的两个方法就很清晰
private HostAndPort initSentinels(Set sentinels, final String masterName) {
HostAndPort master = null;
boolean sentinelAvailable = false;
log.info("Trying to find master from available Sentinels...");
for (String sentinel : sentinels) {
final HostAndPort hap = HostAndPort.parseString(sentinel);
log.fine("Connecting to Sentinel " + hap);
Jedis jedis = null;
try {
jedis = new Jedis(hap.getHost(), hap.getPort());
//从RedisSentinel中获取Master信息
List masterAddr = jedis.sentinelGetMasterAddrByName(masterName);
sentinelAvailable = true; // connected to sentinel...
if (masterAddr == null || masterAddr.size() != 2) {
log.warning("Can not get master addr, master name: " + masterName + ". Sentinel: " + hap + ".");
continue;
}
master = toHostAndPort(masterAddr);
log.fine("Found Redis master at " + master);
break;
} catch (JedisException e) {
// it should handle JedisException there's another chance of raising JedisDataException
log.warning("Cannot get master address from sentinel running @ " + hap + ". Reason: " + e + ". Trying next one.");
} finally {
if (jedis != null) {
jedis.close();
}
}
}
if (master == null) {
if (sentinelAvailable) {
// can connect to sentinel, but master name seems to not monitored
throw new JedisException("Can connect to sentinel, but " + masterName + " seems to be not monitored...");
} else {
throw new JedisConnectionException("All sentinels down, cannot determine where is " + masterName + " master is running...");
}
}
log.info("Redis master running at " + master + ", starting Sentinel listeners...");
//启动后台线程监控RedisSentinal的主从切换通知
for (String sentinel : sentinels) {
final HostAndPort hap = HostAndPort.parseString(sentinel);
MasterListener masterListener = new MasterListener(masterName, hap.getHost(), hap.getPort());
// whether MasterListener threads are alive or not, process can be stopped
masterListener.setDaemon(true);
masterListeners.add(masterListener);
masterListener.start();
}
return master;
}private void initPool(HostAndPort master) {
if (!master.equals(currentHostMaster)) {
currentHostMaster = master;
if (factory == null) {
factory = new JedisFactory(master.getHost(), master.getPort(), connectionTimeout, soTimeout, password, database, clientName, false, null, null, null);
initPool(poolConfig, factory);
} else {
factory.setHostAndPort(currentHostMaster);
// although we clear the pool, we still have to check the returned object
// in getResource, this call only clears idle instances, not
// borrowed instances
internalPool.clear();
}
log.info("Created JedisPool to master at " + master);
}
}可以看到,JedisSentinel的监控时使用MasterListener这个对象来实现的。看对应源码可以发现是基于Redis的订阅实现的,其订阅频道为"+switch-master"。当MasterListener接收到switch-master消息时候,会使用新的Host和port进行initPool。这样对连接池中的连接对象清除,重新创建新的连接指向新的Master服务。
4. 客户端分片
对于大应用来说,单台Redis服务器肯定满足不了应用的需求。在Redis3.0之前,是不支持集群的。如果要使用多台Reids服务器,必须采用其他方式。很多公司使用了代理方式来解决Redis集群。对于Jedis,也提供了客户端分片的模式来连接“Redis集群”。其内部是采用Key的一致性hash算法来区分key存储在哪个Redis实例上的。
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(500);
config.setTestOnBorrow(true);
List jdsInfoList = new ArrayList<>(2);
jdsInfoList.add(new JedisShardInfo("192.168.2.128", 6379));
jdsInfoList.add(new JedisShardInfo("192.168.2.108", 6379));
pool = new ShardedJedisPool(config, jdsInfoList, Hashing.MURMUR_HASH, Sharded.DEFAULT_KEY_TAG_PATTERN);
jds.set(key, value);
......
jds.close();
pool.close();当然,采用这种方式也存在两个问题
扩容问题: 因为使用了一致性哈稀进行分片,那么不同的key分布到不同的Redis-Server上,当我们需要扩容时,需要增加机器到分片列表中,这时候会使得同样的key算出来落到跟原来不同的机器上,这样如果要取某一个值,会出现取不到的情况。
单点故障问题: 当集群中的某一台服务挂掉之后,客户端在根据一致性hash无法从这台服务器取数据。对于扩容问题,Redis的作者提出了一种名为Pre-Sharding的方式。即事先部署足够多的Redis服务。 对于单点故障问题,我们可以使用Redis的HA高可用来实现。利用Redis-Sentinal来通知主从服务的切换。当然,Jedis没有实现这块。我将会在下一篇文章进行介绍。
5. 小结
对于Jedis的基本使用还是很简单的。要根据不用的应用场景选择对于的使用方式。 另外,Spring也提供了Spring-data-redis包来整合Jedis的操作,另外Spring也单独分装了Jedis(我将会在另外一篇文章介绍)。
作者:曹金桂 链接:http://www.jianshu.com/p/a1038eed6d44 來源:简书
- 以上是Jedis使用教程完整版的内容,更多 整版 使用 教程 jedis 的内容,请您使用右上方搜索功能获取相关信息。
转载于:https://my.oschina.net/airship/blog/2875170
Jedis使用教程完整版相关推荐
- python入门教程完整版(懂中文就能学会)-Python入门教程完整版(懂中文就能学会)...
不过小编的内心是强大的,网友虐我千百遍,我待网友如初恋,因为今天又给大家带来了干货,Python入门教程完整版,完整版啊!完整版! 言归正传,小编该给大家介绍一下这套教程了,希望每个小伙伴都沉迷学习, ...
- python3入门与进阶笔记_16_变量进阶 — 黑马程序员《Python入门教程完整版》笔记...
变量进阶(理解) - 黑马程序员<Python入门教程完整版>笔记 目标变量的引用 可变和不可变类型 局部变量和全局变量 01. 变量的引用变量 和 数据 都是保存在 内存 中的 在 Py ...
- JavaScript(基础、高级)笔记汇总表【尚硅谷JavaScript全套教程完整版】
目 录 前言 JavaScript(基础+高级)配套资料下载 JavaScript 基础 学习地址 学习笔记 day 05(P001-P006)[2016.11.22] day 06(P007-P ...
- android+客户端+教程,Android新浪客户端开发教程完整版.pdf
Android新浪客户端开发教程完整版 Android 新浪客户端开发教程新浪客户端开发教程 (完整版(完整版)) 新浪客户端开发教程新浪客户端开发教程 ((完整版完整版)) android开发我的新 ...
- VMware虚拟机去虚拟化完整版教程|永久过强壳VMP、SE壳、GK盾、TMD教程|VMware去虚拟化吾爱汇编论坛教程完整版
VMware去虚拟化完整版教程|永久过强壳VMP.SE壳.GK盾.TMD|VMware去虚拟化吾爱汇编论坛教程完整版 教程内容: 实际效果:
- 阿哈c语言教程pdf,C++教程-完整版.pdf
C教程-完整版 c++基础教程Beta 版 原作: Juan Soulie 翻译: Jing Xu (aqua) 英文原版 本教程根据Juan Soulie 的英文版c++教程翻译并改编. 本版为最新 ...
- python新手教程全套_Python入门教程完整版(懂中文就能学会)
前几天给大家分享视频<python基础教程>受到了广泛的关注,有人不知道怎么领取,居然称小编为"骗子". 不过小编的内心是强大的,网友虐我千百遍,我待网友如初恋,因为今 ...
- React-高级教程完整版
React 高级教程完整版 这标题可能有点不太贴切或符合内容,从官方上来区分这部分内容确实属于高级部分,只是由于个人原因,在后面的一些章节并没有记录在列. 也为了承接上一篇,因此勉强将标题定位:&qu ...
- Python入门教程完整版
今天本宝宝给大家带来了干货,Python入门教程完整版,完整版啊!完整版! 言归正传,我来给大家介绍一下这套教程,希望每个小伙伴都沉迷学习,无法自拔! 本套教程学习时间15天 1-3天内容:为Linu ...
最新文章
- CTFshow php特性 web131
- Java多线程(一):Runnable和Thread的基本用法
- 安装MySQL之后,在cmd中MySQL命令不能识别
- Redis Scan 命令
- JFrame小练习1
- 窗体之间传递值的几种方法
- SVProgressHUD的使用
- idea 导入spring 源码 踩坑记总结整理
- oracle 表空间达到32g,oracle表空间到32G后扩容
- 关于websocket兼容IE版本
- 用安卓软件MT管理器破解元气骑士内购,小白照着也可以成功!
- 【JavaScript】三种方式入手JS弹窗
- python读取yml文件
- Matlab 实现两种读取文件夹内所有图像的方法
- 计算机音乐吧粉刷匠,奥尔夫小班音乐活动:《粉刷匠》
- 微信支付:appid 与 openId 不配
- Windows_XP SP3 Profession 正版密钥
- 《University Calculus》-chaper8-无穷序列和无穷级数-比值审敛法
- 用户登陆成功修改SessionId
- C语言实现可伸缩的栈结构