一、简介
Jedis是支持事务、管道和集成了Redis的一些命令操作的Java客户端。提供了连接池管理,对redis数据的操作。但一般不直接使用jedis,而是再封装一层,作为业务的使用。
官方文档
一、使用
启动redis,默认端口6379,非本机连接需修改配置文件
# 不绑定,接受所有IP的连接请求
# bind 127.0.0.1
# 关闭保护模式
protected-mode no
放行6379端口
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
# 保存配置
service iptables save
1.单机环境
新建个连接池类
//连接池对象
private static JedisPool pool;
//最大连接数
private static Integer maxTotal = 20;
//在jedispool中最大的idle状态(空闲的)的jedis实例的个数
private static Integer maxIdle = 20;
//在jedispool中最小的idle状态(空闲的)的jedis实例的个数
private static Integer minIdle = 20;
//获得jedis实例的时候是否要进行验证操作,如果赋值true。则得到的jedis实例肯定是可以用的。
private static Boolean testOnBorrow = true;
//在归还jedis实例的时候是否要进行验证操作,如果赋值true。则放回l的jedis实例肯定是可以用的。
private static Boolean testOnReturn = true;
private static String redisIp = "192.168.8.10";
private static Integer redisPort = 6379;
/**
* 初始化连接池
*/
private static void initPool() {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setTestOnBorrow(testOnBorrow);
config.setTestOnReturn(testOnReturn);
//连接耗尽的时候,是否阻塞,false会抛出异常,true阻塞直到超时。默认为true。
config.setBlockWhenExhausted(true);
pool = new JedisPool(config, redisIp, redisPort, 1000 * 2);
}
static {
initPool();
}
//获取连接对象
public static Jedis getJedis() {
return pool.getResource();
}
//归还连接对象
public static void returnResource(Jedis jedis) {
//todo close
jedis.close();
}
//测试
public static void main(String[] args) {
Jedis jedis = pool.getResource();
jedis.set("kekeke", "veveveveve");
returnResource(jedis);
pool.destroy();//销毁连接池中的所有连接
System.out.println("end");
}
方便使用再封装一个工具类
//设置key的有效期,单位秒
public static Long expire(String key, int exTime) {
Jedis jedis = null;
Long result = null;
try {
jedis = RedisPool.getJedis();
result = jedis.expire(key, exTime);
} catch (Exception e) {
e.printStackTrace();
RedisPool.returnResource(jedis);
return result;
}
RedisPool.returnResource(jedis);
return result;
}
//添加key-value时同时设置有效期,单位秒
public static String setEx(String key, String value, int exTime) {
Jedis jedis = null;
String result = null;
try {
jedis = RedisPool.getJedis();
result = jedis.setex(key, exTime, value);
} catch (Exception e) {
e.printStackTrace();
RedisPool.returnResource(jedis);
return result;
}
RedisPool.returnResource(jedis);
return result;
}
//添加永久key-value
public static String set(String key, String value) {
Jedis jedis = null;
String result = null;
try {
jedis = RedisPool.getJedis();
result = jedis.set(key, value);
} catch (Exception e) {
e.printStackTrace();
RedisPool.returnResource(jedis);
return result;
}
RedisPool.returnResource(jedis);
return result;
}
//获取值
public static String get(String key) {
Jedis jedis = null;
String result = null;
try {
jedis = RedisPool.getJedis();
result = jedis.get(key);
} catch (Exception e) {
e.printStackTrace();
RedisPool.returnResource(jedis);
return result;
}
RedisPool.returnResource(jedis);
return result;
}
//删除key-value
public static Long del(String key) {
Jedis jedis = null;
Long result = null;
try {
jedis = RedisPool.getJedis();
result = jedis.del(key);
} catch (Exception e) {
e.printStackTrace();
RedisPool.returnResource(jedis);
return result;
}
RedisPool.returnResource(jedis);
return result;
}
//测试
public static void main(String[] args) {
RedisPoolUtil.setEx("keyex", "valuex", 60 * 10);
String value = RedisPoolUtil.get("keyex");
System.out.println(value);
System.out.println("end");
}
管道和事物
// Transactions,事务方式,监听一些key的值是否改变来决定是否执行
public static void jedisTransactions() {
Jedis jedis = RedisPool.getJedis();
long start = System.currentTimeMillis();
Transaction tx = jedis.multi();
for (int i = 0; i < 100000; i++) {
tx.set("t" + i, "t" + i);
}
//监听,其值改变则回滚
jedis.watch("testabcd");
List<Object> results = tx.exec();
long end = System.currentTimeMillis();
System.out.println("Transaction SET: " + ((end - start)/1000.0) + " seconds");
jedis.close();
}
// Pipelining 管道技术,可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。
public static void jedisPipelining() {
Jedis jedis = RedisPool.getJedis();
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.close();
}
//管道中调用事务
public static void jedisCombPipelineTrans() {
Jedis jedis = RedisPool.getJedis();
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.close();
}
可以看到管道技术大大的提高了执行效率,但它不支持事物,把事物放到管道中执行效率介于两者之间
2.多机环境
ShardedJedis是基于一致性哈希算法实现的分布式Redis集群客户端
首先修改配置文件中的端口号,再开启一个Redis
新建个连接池类,和单机环境差不多,只是连接池对象不一样
//sharded jedis连接池
private static ShardedJedisPool pool;
private static Integer maxTotal = 20;
private static Integer maxIdle = 20;
private static Integer minIdle = 20;
private static Boolean testOnBorrow = true;
private static Boolean testOnReturn = true;
private static String redis1Ip = "192.168.8.10";
private static Integer redis1Port = 6379;
private static String redis2Ip = "192.168.8.10";
private static Integer redis2Port = 6380;
private static void initPool() {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setTestOnBorrow(testOnBorrow);
config.setTestOnReturn(testOnReturn);
JedisShardInfo info1 = new JedisShardInfo(redis1Ip, redis1Port, 1000 * 2);
JedisShardInfo info2 = new JedisShardInfo(redis2Ip, redis2Port, 1000 * 2);
List<JedisShardInfo> jedisShardInfoList = new ArrayList<JedisShardInfo>(2);
jedisShardInfoList.add(info1);
jedisShardInfoList.add(info2);
//分布式算法使用MURMUR_HASH,分布式策略使用DEFAULT_KEY_TAG_PATTERN
pool = new ShardedJedisPool(config, jedisShardInfoList, Hashing.MURMUR_HASH, Sharded.DEFAULT_KEY_TAG_PATTERN);
}
static {
initPool();
}
public static ShardedJedis getJedis() {
return pool.getResource();
}
public static void returnResource(ShardedJedis jedis) {
jedis.close();
}
public static void main(String[] args) {
ShardedJedis jedis = getJedis();
for (int i = 0; i < 10; i++) {
jedis.set("key" + i, "value" + i);
}
returnResource(jedis);
pool.destroy();//临时调用,销毁连接池中的所有连接
System.out.println("program is end");
}
分布式中管道技术,即异步调用,分布式调用中不支持事务,因为事务是在服务器端实现,而分布式中每次访问的服务器可能不同
public static void jedisShardPipelinedPool() {
ShardedJedis one = getJedis();
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();
one.close();
System.out.println("Pipelined SET: " + ((end - start)/1000.0) + " seconds");
}