一、客户端通信协议

  二、Java客户端Jedis

  1.获取Jedis

  Jedis属于Java的第三方开发包,在Java中获取第三方开发包通常有两种方式:

  • 直接下载目标版本的Jedis-${version}.jar包加入到项目中。
  • 使用集成构建工具,例如maven、gradle等将Jedis目标版本的配置加入到项目中。

  2.Jedis的基本使用方法

  本次使用的jar包为:jedis-2.9.0.jar

bigjun@myubuntu:/home/workspace/JedisTest$ tree
.
├── bin
│   └── ubuntuJedis.class
├── lib
│   └── jedis-2.9..jar
└── src
└── ubuntuJedis.java directories, files

  Jedis构造器:

Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout)
host:Redis实例的所在机器的IP
port:Redis实例的端口
connectionTimeout:客户端连接超时
soTimeout:客户端读写超时

  先看一个简单的代码实现set和get功能:

package JedisTest;
import redis.clients.jedis.Jedis;
public class JedisTest { public static void main(String[] args) {
@SuppressWarnings("resource")
Jedis jedis = new Jedis("localhost"); jedis.set("eclipse", "eclipseJedis");
String getResult = jedis.get("eclipse");
System.out.println(getResult);
}
}

  在实际项目中,比较推荐使用try catch finally的形式来进行代码的书写:一方面可以在Jedis出现异常的时候(本身是网络操作),将异常进行捕获或者抛出;另一个方面无论执行成功或者失败,将Jedis连接关闭掉,在开发中关闭不用的连接资源是一种好的习惯,代码类似如下:

package JedisTest;
import redis.clients.jedis.Jedis;
public class JedisTest { public static void main(String[] args) {
Jedis jedis = null;
try {
jedis = new Jedis("127.0.0.1", 6379);
String string = jedis.get("hello");
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}

  给出Jedis对五种数据结构的操作:

// 1.string
// 输出结果: OK
jedis.set("hello", "world");
// 输出结果: world
jedis.get("hello");
// 输出结果: 1
jedis.incr("counter"); // 2.hash
jedis.hset("myhash", "f1", "v1");
jedis.hset("myhash", "f2", "v2");
// 输出结果: {f1=v1, f2=v2}
jedis.hgetAll("myhash"); // 3.list
jedis.rpush("mylist", "1");
jedis.rpush("mylist", "2");
jedis.rpush("mylist", "3");
// 输出结果: [1, 2, 3]
jedis.lrange("mylist", 0, -1); // 4.set
jedis.sadd("myset", "a");
jedis.sadd("myset", "b");
jedis.sadd("myset", "a");
// 输出结果: [b, a]
jedis.smembers("myset"); // 5.zset
jedis.zadd("myzset", 99, "tom");
jedis.zadd("myzset", 66, "peter");
jedis.zadd("myzset", 33, "james");
// 输出结果: [[["james"],33.0], [["peter"],66.0], [["tom"],99.0]]
jedis.zrangeWithScores("myzset", 0, -1);

  3.序列化和反序列化:

  有了上述这些API的支持,就可以将Java对象序列化为二进制,当应用需要获取Java对象时,使用get(final byte[]key)函数将字节数组取出,然后反序列化为Java对象即可。

  和很多NoSQL数据库(例如Memcache、Ehcache)的客户端不同,Jedis本身没有提供序列化的工具,也就是说开发者需要自己引入序列化的工具。

  常用的序列化工具为JDK、XML、JSON和Protostuff,这几种序列化工具在Jedis中的使用见另外的一篇博客。

  4.Jedis连接池的使用方法

  (1)直连方式

  直连是指Jedis每次都会新建TCP连接,使用后再断开连接,对于频繁访问Redis的场景显然不是高效的使用方式。

  

  (2)连接池方式

  生产环境中一般使用连接池的方式对Jedis连接进行管理,Jedis对象预先放在连接池(JedisPool)中,每次要连接Redis,只需要在池子中借,用完了再归还给池子。

  

  (3)Jedis直连方式和连接池方式对比

  

  (4)Jedis连接池方式示例

  JedisPool版本:commons-pool2-2.5.0.jar

  • 使用默认连接池配置来实现Redis的连接
package bigjun.iplab.jedisPoolTest;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool; public class JedisPoolTest {
public static void main(String[] args) {
// 连接池配置,这里使用默认配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
@SuppressWarnings("resource")
// 初始化Jedis连接池
JedisPool jedisPool = new JedisPool(poolConfig, "192.168.131.130", 6379);
Jedis jedis = null;
try {
// 从连接池获取jedis对象
jedis = jedisPool.getResource();
// 执行操作
String getResult = jedis.get("Lua");
System.out.println(getResult);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}
  • Jedis中的close()方法
  @Override
public void close() {
   // 如果连接池正在使用
if (dataSource != null) {
    // 如果连接断开,就返还连接给连接池
if (client.isBroken()) {
this.dataSource.returnBrokenResource(this);
} else {
this.dataSource.returnResource(this);
}
   // 直连方式的时候,关闭连接
} else {
client.close();
}
}
  • 连接池配置的配置方法
// 默认配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// 设置最大连接数为默认值的 5 倍
poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 5);
// 设置最大空闲连接数为默认值的 3 倍
poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 3);
// 设置最小空闲连接数为默认值的 2 倍
poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE * 2);
// 设置开启 jmx 功能
poolConfig.setJmxEnabled(true);
// 设置连接池没有连接后客户端的最大等待时间 ( 单位为毫秒 )
poolConfig.setMaxWaitMillis(3000);

  5.Jedis中Pipeline使用方法

  示例背景:Redis提供了mget、mset方法,但是没有提供mdel方法,可以用Pipeline来模拟批量删除,虽然不想mset和mget是原子命令,但是绝大时候可以使用。

  (1)使用sync()执行命令

public void mdel(List<String> keys) {
Jedis jedis = new Jedis("127.0.0.1");
// 1) 生成 pipeline 对象
Pipeline pipeline = jedis.pipelined();
// 2)pipeline 执行命令,注意此时命令并未真正执行
for (String key : keys) {
pipeline.del(key);
}
// 3) 执行命令
pipeline.sync();
}

  (2)使用syncAndReturnAll()方法执行命令并获得返回值

Jedis jedis = new Jedis("127.0.0.1");
Pipeline pipeline = jedis.pipelined();
pipeline.set("hello", "world");
pipeline.incr("counter");
List<Object> resultList = pipeline.syncAndReturnAll();
for (Object object : resultList) {
System.out.println(object);
}

  6.Jedis的Lua脚本

  (1)Jedis的三个重要的函数:

Object eval(String script, int keyCount, String... params)
Object evalsha(String sha1, int keyCount, String... params)
String scriptLoad(String script) script:Lua脚本内容。
sha1:脚本的SHA1.
keyCount:键的个数。
params:相关参数KEYS和ARGV。

  (2)使用eval()方法

  在Redis中执行Lua脚本:

192.168.131.130:> get Lua
"Redis"
192.168.131.130:> eval 'return redis.call("get", KEYS[1])' Lua
"Redis"

  在Jedis中执行相同的Lua脚本:

        try {
// 从连接池获取jedis对象
jedis = jedisPool.getResource();
// 执行操作
String key = "Lua";
String script = "return redis.call('get', KEYS[1])";
Object result = jedis.eval(script, 1, key);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}

  (3)使用scriptLoad()和evalsha()方法

        try {
// 从连接池获取jedis对象
jedis = jedisPool.getResource();
// 执行操作
String key = "Lua";
String script = "return redis.call('get', KEYS[1])";
String scriptSha1 = jedis.scriptLoad(script);
Object result = jedis.evalsha(scriptSha1, 1, key);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}

  四、客户端管理

  1.客户端API

  (1)client list

  

  

192.168.131.130:> client list
id= addr=192.168.131.130: fd= name= age= idle= flags=N db= sub= psub= multi=- qbuf= qbuf-free= obl= oll= omem= events=r cmd=client
id= addr=192.168.131.130: fd= name= age= idle= flags=N db= sub= psub= multi=- qbuf= qbuf-free= obl= oll= omem= events=r cmd=keys id:客户端连接的唯一标识
addr:客户端连接的ip和端口
fd:socket的文件描述符
name:客户端的名字 age:当前客户端已经连接的时间
idle:当前客户端最近一次的空闲时间 flags:标识当前客户端的类型(N:普通客户端;S:slave客户端等11种客户端类型) qbuf:输入缓冲区的总容量
qbuf-free:输入缓冲区的剩余容量 obl:输出缓冲区固定缓冲区的长度
oll:输出缓冲区动态缓冲区列表的长度
omen:输出缓冲区使用的字节
  • 输入缓冲区

  

  监控输入缓冲区异常的两种方法:

  

  • 输出缓冲区

  

  按照客户端的不同分为三种:普通客户端、发布订阅客户端、slave客户端

  输出缓冲区的容量可以通过参数client-output-buffer-limit来进行设置

  和输入缓冲区一样有两种监控方法:client list和info clients

  (2)client setName和client getName

  在Redis只有一个应用方使用的情况下,IP和端口作为标识会更加清晰;当多个应用方共同使用一个Redis,client setName可以作为标识客户端的一个依据。

192.168.131.130:> client setName haveName_client
OK
192.168.131.130:> client list
id= addr=192.168.131.130: fd= name=haveName_client age= idle= flags=N db= sub= psub= multi=- qbuf= qbuf-free= obl= oll= omem= events=r cmd=client
id= addr=192.168.131.130: fd= name= age= idle= flags=N db= sub= psub= multi=- qbuf= qbuf-free= obl= oll= omem= events=r cmd=keys
192.168.131.130:> client getName
"haveName_client"

  (3)client kill ip:port

192.168.131.130:> client list
id= addr=192.168.131.130: fd= name=haveName_client age= idle= flags=N db= sub= psub= multi=- qbuf= qbuf-free= obl= oll= omem= events=r cmd=client
id= addr=192.168.131.130: fd= name= age= idle= flags=N db= sub= psub= multi=- qbuf= qbuf-free= obl= oll= omem= events=r cmd=keys
192.168.131.130:> client kill 192.168.131.130:
OK
192.168.131.130:> client list
id= addr=192.168.131.130: fd= name=haveName_client age= idle= flags=N db= sub= psub= multi=- qbuf= qbuf-free= obl= oll= omem= events=r cmd=client

  (4)阻塞客户端连接:client pause timeout(毫秒)

客户端1:
192.168.131.130:> client pause
OK 客户端2:
192.168.131.130:> ping
PONG
(.00s)

  (5)监控Redis正在执行的命令:monitor

客户端1:
192.168.131.130:> monitor
OK 客户端2:
(.00s)
192.168.131.130:> get Lua
"Redis"
192.168.131.130:> ping
PONG 客户端1:
192.168.131.130:> monitor
OK
1528182107.437256 [ 192.168.131.130:] "get" "Lua"
1528182112.634521 [ 192.168.131.130:] "ping"
...

  2.客户端相关配置

timeout:检测客户端空闲连接的超时时间,一旦idle时间达到了timeout,客户端将会被关闭,如果设置为0就不进行检测。
maxclients:客户端最大连接数赘述,这个参数会受到操作系统设置的限制,
tcp-keepalive:检测TCP连接活性的周期,默认值为0,也就是不进行检测,如果需要设置,建议为60,那么Redis会每隔60秒对它创建的TCP连接进行活性检测,防止大量死连接占用系统资源。
tcp-backlog:TCP三次握手后,会将接受的连接放入队列中,tcp-backlog就是队列的大小,它在Redis中的默认值是511

  3.客户端统计片段 

192.168.131.130:> info clients
# Clients
connected_clients:
client_longest_output_list:
client_biggest_input_buf:
blocked_clients: connected_clients:当前Redis节点的客户端连接数
client_longest_output_list:当前所有输出缓冲区中队列对象个数的最大值
client_biggest_input_buf:当前所有输入缓冲区中占用的最大容量
blocked_clients:正在执行阻塞命令的客户端的个数 192.168.131.130:> info stats
# Stats
total_connections_received:
total_commands_processed:
instantaneous_ops_per_sec:
total_net_input_bytes:
total_net_output_bytes:
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:
...

  五、客户端常见异常

  1.无法从连接池获取到连接

  2.客户端读写超时

  3.客户端连接超时

  4.客户端缓冲区异常

  5.Lua脚本正在执行

  6.Redis正在加载持久化文件

  7.Redis使用的内存超过maxmemory配置

  8.客户端连接数过大

Redis(四)Jedis客户端的更多相关文章

  1. 扩展Redis的Jedis客户端,哨兵模式读请求走Slave集群

    原 扩展Redis的Jedis客户端,哨兵模式读请求走Slave集群 2018年12月06日 14:26:45 温故而知新666 阅读数 897   版权声明:本文为博主原创文章,遵循CC 4.0 b ...

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

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

  3. 【转载】Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式…)介绍

    转载地址:http://blog.csdn.net/truong/article/details/46711045 关键字:Redis的Java客户端Jedis的八种调用方式(事务.管道.分布式…)介 ...

  4. Jedis客户端即redis中的pipeline批量操作

    关注公众号:CoderBuff,回复"redis"获取<Redis5.x入门教程>完整版PDF. <Redis5.x入门教程>目录 第一章 · 准备工作 第 ...

  5. Redis集群的使用测试(Jedis客户端的使用)

    Redis集群的使用测试(Jedis客户端的使用)1.Jedis客户端建议升级到最新版(当前为2.7.3),这样对3.0.x集群有比较好的支持.https://github.com/xetorthio ...

  6. Redis的java客户端jedis

    导包:Jedis需要的jar包 >Commons-pool-1.6.jar >Jedis-2.1.0.jar 配置:linux防火墙设置,不会设置就关闭. 停止防火墙 systemctl ...

  7. Redis服务器搭建/配置/及Jedis客户端的使用方法

    摘要 Redis服务器搭建.常用参数含意说明.主从配置.以及使用Jedis客户端来操作Redis Redis服务器搭建 安装 在命令行执行下面的命令: $ wget http://download.r ...

  8. Redis学习十一:Redis的Java客户端Jedis

    一.安装JDK tar -zxvf jdk-7u67-linux-i586.tar.gz vi /etc/profile 重启一次Centos 编码验证 二.安装eclipse 三.Jedis所需要的 ...

  9. Redis(九):Redis的Java客户端Jedis

    Redis的Java客户端Jedis导航目录: 安装JDK 安装Eclipse Jedis所需要的Jar包 Jedis常用操作 JedisPool 安装JDK tar -zxvf jdk-7u67-l ...

随机推荐

  1. hbase配置-集群无法启动问题

    root@cslave2:/]#jps 2834 NodeManager 2487 DataNode 12282 Jps 2415 QuorumPeerMain root@cslave2:/]#sud ...

  2. codeforce-1201-C题解

    题目:给你一个包含n个整数的数组A(n为奇数),对A做k次以下操作: 对数组排序使数组以非递减顺序排列. 选取数组的中位数,然后加一 最终使得数组的中位数最大. 输入:第一行输入两个数字 n 和 k ...

  3. 阿里云服务器CentOS6.9防火墙启动无效--iptables消失

    iptables 是与最新的 3.5 版本 Linux 内核集成的 IP 信息包过滤系统.如果 Linux 系统连接到因特网或 LAN.服务器或连接 LAN 和因特网的代理服务器, 则该系统有利于在 ...

  4. Angular 元素拖拽

    拖动元素到指定区域 拖放的同时传递数据 1. 安装 ng2-drag-drop npm install ng2-drag-drop --save 2. 模板中配置可拖拽元素 // drag.compo ...

  5. 微信公众平台开发(57)Emoji表情符号 【转发】

    微信公众平台开发(57)Emoji表情符号   微信公众平台开发 微信公众平台开发模式 企业微信公众平台 Emoji表情符号 作者:方倍工作室 地址:http://www.cnblogs.com/tx ...

  6. java几个常见的基础错误

    1.String 相等 稍微有点经验的程序员都会用equals比较而不是用 ==,但用equals就真的安全了吗,看下面的代码 user.getName().equals("xiaoming ...

  7. 写了那么多年 Java 代码,终于 debug 到 JVM 了

    继上篇文章 原创 | 全网最新最简单的 openjdk13 代码编译 之后,我们有了自己编译后的 jdk 和 hotspot,如下图所示.接下来就来干一番事情. 搭建调试环境 1.下载 CLion 软 ...

  8. IDEA统一注释格式(干货)

    统一注释格式: Idea自动生成注释: /** *@author 你的名字的简写 *@date ${DATE}${TIME} 在每个功能上添加注释,例子如下: 我在Mapper文件中添加了自己书写的S ...

  9. 个性化推荐产品功能的设计和B端产品的功能策划方式

    宜信科技中心财富管理产品部负责人Bob,与大家一起聊聊个性化推荐产品功能的设计和B端产品的功能策划方式. 拓展阅读:回归架构本质,重新理解微服务|专访宜信开发平台(SIA)负责人梁鑫 智慧金融时代,大 ...

  10. Spring Cloud之Hystrix

    在微服务架构中,存在那么多的服务单元,若一个单元出现故障(由于网络原因或者自身原因),就很容易因依赖关系而引发故障的蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构更加不稳定.为了解决这样的问题, ...