Redis 默认是不支持远程连接的,需要手动开启,需要配置 redis.conf 文件:
警告说,如果打算直接暴露到网上,谁都可以连接,是危险的,建议强制直接配置的 IPV4 地址,这样只有配置的地址才能连接,由于我的 Redis 在 CentOS 虚拟机的 Ubuntu 系统中,所以我需要暴露到网上,此时比较危险,所以我设置了 redis 的连接密码,密码:javaboy
创建一个 Maven 项目,并在 github 上查询 Jedis 的依赖,添加到项目中
public class MyJedis {
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.21.129");
jedis.auth("javaboy");
String ping = jedis.ping();
System.out.println(ping);
String set = jedis.set("name", "xuanjinnan");
System.out.println(set);
String name = jedis.get("name");
System.out.println(name);
}
}
直接 new 就可以,地址是 ubuntu 运行 ip addr ,ens33 中的内容
运行查看控制台,说明连接上 Redis ,并能正常使用了
期间,第一次没连上,重启了一下 Redis 就好了
对于 Jedis 而言,一旦连上 Redis 服务,接下来操作都很容易,因为方法的 API 与 Redis 命令高度一致,所以 Jedis 中的方法见名知义直接使用即可
在实际用中,Jedis 实例一般通过连接池来获取,由于 Jedis 不是现场安全的,所以当我们使用 Jedis 对象时,要从连接池中获取 Jedis,使用完成后再还给连接池,线程池是线程安全的
// 第一步,创建一个连接池
JedisPool jedisPool = new JedisPool("192.168.21.129");
// 第二步,从连接池中获取一个 Jedis 连接
Jedis jedis = jedisPool.getResource();
String javaboy = jedis.auth("javaboy");
System.out.println(javaboy);
// 第三步,执行 Jedis 操作
String ping = jedis.ping();
System.out.println(ping);
// 第四步,归还连接
jedis.close();
运行结果
每个 Jedis Resouce 都是要归还的资源,如果第三步出错,导致第四步没有执行,会有内存泄露的风险,所以我们要对代码进行优化,保证第四步能够执行
// 第一步,创建一个连接池
JedisPool jedisPool = new JedisPool("192.168.21.129");
// 第二步,从连接池中获取一个 Jedis 连接
Jedis jedis = jedisPool.getResource();
String javaboy = jedis.auth("javaboy");
System.out.println(javaboy);
// 第三步,执行 Jedis 操作
try {
String ping = jedis.ping();
System.out.println(ping);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 第四步,归还连接
if(jedis != null){
jedis.close();
}
}
通过 finally,我们可以确保 Jedis 一定被关闭
还可以利用 JDK 1.7 的资源释放语法糖进行简写:
// 第一步,创建一个连接池
JedisPool jedisPool = new JedisPool("192.168.21.129");
// 第二步,从连接池中获取一个 Jedis 连接
try(Jedis jedis = jedisPool.getResource()){
String javaboy = jedis.auth("javaboy");
System.out.println(javaboy);
// 第三步,执行 Jedis 操作
String ping = jedis.ping();
System.out.println(ping);
}
这段代码的作用和 try - catch - finally 是一样的
但是又有一个弊端,每次一定要执行 close() 方法,如果忘了呢,就有可能资源释放不了,无法做到强约束,我们可以通过设计模式,把 第三部 Jedis 操作抽象出去,整个过程方法起名叫 excute,第三部抽象出一个方法叫 callJedis,那么代码可以首先是
public class Redis {
private static JedisPool pool = new JedisPool( "192.168.21.129");
public void execute(CallWithJedis callWithJedis){
try(Jedis jedis = pool.getResource()){
jedis.auth("javaboy");
callWithJedis.callJedis(jedis);
}
}
}
定义 CallWithJedis 接口 和 callJedis 抽象方法,callJedis 就是实际执行的 Jedis 操作方法:
public interface CallWithJedis {
void callJedis(Jedis jedis);
}
使用时:
Redis redis = new Redis();
redis.execute(jedis -> {
System.out.println(jedis.ping());
});
这就是最终的优化方案
public class Redis {
private static GenericObjectPoolConfig<String> config ;
static {
config= new GenericObjectPoolConfig<String>();
// 最大空闲数量
config.setMaxIdle(300);
// 最大线程数
config.setMaxTotal(1000);
// 最大连接等待时间,-1 表示无限制
config.setMaxWaitMillis(30000);
// 在空闲时校验有效性
config.setTestOnBorrow(true);
}
private static JedisPool pool = new JedisPool(config, "192.168.21.129", 6379, 3000, "javaboy");
public void execute(CallWithJedis callWithJedis){
try(Jedis jedis = pool.getResource()){
callWithJedis.callJedis(jedis);
}
}
}
在分布式中有许多情况要重试,比如 Spring Cloud Config,同样,获取 Jedis 资源也可能失败,我们这时候可以加上重试功能,这里重试三次
public class Redis {
private static GenericObjectPoolConfig<String> config ;
static {
config= new GenericObjectPoolConfig<String>();
// 最大空闲数量
config.setMaxIdle(300);
// 最大线程数
config.setMaxTotal(1000);
// 最大连接等待时间,-1 表示无限制
config.setMaxWaitMillis(30000);
// 在空闲时校验有效性
config.setTestOnBorrow(true);
}
private static JedisPool pool = new JedisPool(config, "192.168.21.129", 6379, 3000, "javaboy");
public void execute(CallWithJedis callWithJedis){
Jedis jedis = null;
try{
jedis = pool.getResource();
callWithJedis.callJedis(jedis);
}catch (Exception e0){
try {
Thread.sleep(2000);
jedis = pool.getResource();
callWithJedis.callJedis(jedis);
} catch (Exception e1) {
try {
Thread.sleep(2000);
jedis = pool.getResource();
callWithJedis.callJedis(jedis);
} catch (Exception e2) {
e2.printStackTrace();
}
}
}finally {
if (jedis != null) {
jedis.close();
}
}
}
}
重试的代码丑陋,也可能有很多可以优化的地方,仅作为重试想法 demo,看看即可
github地址
Lettus 和 Jedis 比较
Lettuce简单使用
public class LettusTest {
public static void main(String[] args) {
RedisClient redisClient = RedisClient.create("redis://[email protected]");
StatefulRedisConnection<String, String> connect = redisClient.connect();
RedisCommands<String, String> sync = connect.sync();// 同步
String set = sync.set("name", "xuanjinnan");
System.out.println(set);
String name = sync.get("name");
System.out.println(name);
}
}