package com.javaweb.redis.util;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import redis.clients.jedis.*;
|
|
import java.io.*;
|
import java.util.*;
|
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
/**
|
* Redis client base on jedis
|
*
|
* @author wujiyue 2015-7-10 18:34:07
|
*/
|
public class InitRedisUtil {
|
private static Logger logger = LoggerFactory.getLogger(InitRedisUtil.class);
|
|
/**
|
* redis address, like "{ip}"、"{ip}:{port}"、"{redis/rediss}://域名:{password}@{ip}:{port:6379}/{db}";Multiple "," separated
|
*/
|
private static String address;
|
|
public static boolean initFlag=false;
|
public static void init(String address) {
|
InitRedisUtil.address = address;
|
|
getInstance();
|
}
|
|
// ------------------------ ShardedJedisPool ------------------------
|
/**
|
* 方式01: Redis单节点 + Jedis单例 : Redis单节点压力过重, Jedis单例存在并发瓶颈 》》不可用于线上
|
* new Jedis("127.0.0.1", 6379).get("cache_key");
|
* 方式02: Redis单节点 + JedisPool单节点连接池 》》 Redis单节点压力过重,负载和容灾比较差
|
* new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379, 10000).getResource().get("cache_key");
|
* 方式03: Redis分片(通过client端集群,一致性哈希方式实现) + Jedis多节点连接池 》》Redis集群,负载和容灾较好, ShardedJedisPool一致性哈希分片,读写均匀,动态扩充
|
* new ShardedJedisPool(new JedisPoolConfig(), new LinkedList<JedisShardInfo>());
|
* 方式03: Redis集群;
|
* new JedisCluster(jedisClusterNodes); // TODO
|
*/
|
|
private static ShardedJedisPool shardedJedisPool;
|
private static ReentrantLock INSTANCE_INIT_LOCL = new ReentrantLock(false);
|
|
/**
|
* 获取ShardedJedis实例
|
*
|
* @return
|
*/
|
private static ShardedJedis getInstance() {
|
if (shardedJedisPool == null) {
|
try {
|
if (INSTANCE_INIT_LOCL.tryLock(2, TimeUnit.SECONDS)) {
|
|
try {
|
|
if (shardedJedisPool == null) {
|
|
// JedisPoolConfig
|
JedisPoolConfig config = new JedisPoolConfig();
|
config.setMaxTotal(200);
|
config.setMaxIdle(50);
|
config.setMinIdle(8);
|
config.setMaxWaitMillis(10000); // 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
|
config.setTestOnBorrow(true); // 在获取连接的时候检查有效性, 默认false
|
config.setTestOnReturn(false); // 调用returnObject方法时,是否进行有效检查
|
config.setTestWhileIdle(true); // Idle时进行连接扫描
|
config.setTimeBetweenEvictionRunsMillis(30000); // 表示idle object evitor两次扫描之间要sleep的毫秒数
|
config.setNumTestsPerEvictionRun(10); // 表示idle object evitor每次扫描的最多的对象数
|
config.setMinEvictableIdleTimeMillis(60000); // 表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
|
|
|
// JedisShardInfo List
|
List<JedisShardInfo> jedisShardInfos = new LinkedList<JedisShardInfo>();
|
|
String[] addressArr = address.split(",");
|
for (int i = 0; i < addressArr.length; i++) {
|
JedisShardInfo jedisShardInfo = new JedisShardInfo(addressArr[i]);
|
jedisShardInfos.add(jedisShardInfo);
|
}
|
shardedJedisPool = new ShardedJedisPool(config, jedisShardInfos);
|
logger.info(">>>>>>>>>>>RedisUtil.ShardedJedisPool init success.");
|
}
|
|
} finally {
|
INSTANCE_INIT_LOCL.unlock();
|
initFlag=true;
|
}
|
}
|
|
} catch (InterruptedException e) {
|
logger.error(e.getMessage(), e);
|
}
|
}
|
|
if (shardedJedisPool == null) {
|
initFlag=false;
|
throw new NullPointerException(">>>>>>>>>>> RedisUtil.ShardedJedisPool is null.");
|
}
|
|
ShardedJedis shardedJedis = shardedJedisPool.getResource();
|
return shardedJedis;
|
}
|
|
public static void close() throws IOException {
|
if(shardedJedisPool != null) {
|
shardedJedisPool.close();
|
}
|
}
|
|
|
// ------------------------ serialize and unserialize ------------------------
|
|
/**
|
* 将对象-->byte[] (由于jedis中不支持直接存储object所以转换成byte[]存入)
|
*
|
* @param object
|
* @return
|
*/
|
private static byte[] serialize(Object object) {
|
ObjectOutputStream oos = null;
|
ByteArrayOutputStream baos = null;
|
try {
|
// 序列化
|
baos = new ByteArrayOutputStream();
|
oos = new ObjectOutputStream(baos);
|
oos.writeObject(object);
|
byte[] bytes = baos.toByteArray();
|
return bytes;
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
try {
|
oos.close();
|
baos.close();
|
} catch (IOException e) {
|
logger.error(e.getMessage(), e);
|
}
|
}
|
return null;
|
}
|
|
/**
|
* 将byte[] -->Object
|
*
|
* @param bytes
|
* @return
|
*/
|
private static Object unserialize(byte[] bytes) {
|
ByteArrayInputStream bais = null;
|
try {
|
// 反序列化
|
bais = new ByteArrayInputStream(bytes);
|
ObjectInputStream ois = new ObjectInputStream(bais);
|
return ois.readObject();
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
try {
|
bais.close();
|
} catch (IOException e) {
|
logger.error(e.getMessage(), e);
|
}
|
}
|
return null;
|
}
|
|
// ------------------------ jedis util ------------------------
|
/**
|
* 存储简单的字符串或者是Object 因为jedis没有分装直接存储Object的方法,所以在存储对象需斟酌下
|
* 存储对象的字段是不是非常多而且是不是每个字段都用到,如果是的话那建议直接存储对象,
|
* 否则建议用集合的方式存储,因为redis可以针对集合进行日常的操作很方便而且还可以节省空间
|
*/
|
/**
|
* Set String
|
*
|
* @param key
|
* @param value
|
* @return
|
*/
|
public static String setStringValue(String key, String value) {
|
String result = null;
|
ShardedJedis client = getInstance();
|
try {
|
result = client.set(key, value);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
|
public static String type(String key) {
|
String result = null;
|
ShardedJedis client = getInstance();
|
try {
|
result = client.type(key);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
public static long ttl(String key) {
|
long result = 0L;
|
ShardedJedis client = getInstance();
|
try {
|
result = client.ttl(key);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
/**
|
* Set String
|
*
|
* @param key
|
* @param value
|
* @param seconds 存活时间,单位/秒
|
* @return
|
*/
|
public static String setStringValue(String key, String value, int seconds) {
|
String result = null;
|
ShardedJedis client = getInstance();
|
try {
|
result = client.setex(key, seconds, value);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
|
/**
|
* Set Object
|
*
|
* @param key
|
* @param obj
|
* @param seconds 存活时间,单位/秒
|
*/
|
public static String setObjectValue(String key, Object obj, int seconds) {
|
String result = null;
|
ShardedJedis client = getInstance();
|
try {
|
// result = client.setex(key.getBytes(), seconds, serialize(obj));
|
result = client.setex(key, seconds, JSON.toJSONString(obj));
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
|
/**
|
* Get String
|
*
|
* @param key
|
* @return
|
*/
|
public static String getStringValue(String key) {
|
String value = null;
|
ShardedJedis client = getInstance();
|
try {
|
value = client.get(key);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return value;
|
}
|
|
/**
|
* Get Object
|
*
|
* @param key
|
* @return
|
*/
|
public static Object getObjectValue(String key) {
|
Object obj = null;
|
ShardedJedis client = getInstance();
|
try {
|
byte[] bytes = client.get(key.getBytes());
|
if (bytes != null && bytes.length > 0) {
|
obj = unserialize(bytes);
|
}
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return obj;
|
}
|
public static Object getObjectValue(String key,Class cls) {
|
Object obj = null;
|
ShardedJedis client = getInstance();
|
try {
|
/* byte[] bytes = client.get(key.getBytes());
|
if (bytes != null && bytes.length > 0) {
|
obj = unserialize(bytes);
|
}*/
|
;
|
obj= JSONObject.parseObject(client.get(key), cls);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return obj;
|
}
|
/**
|
* Delete key
|
*
|
* @param key
|
* @return Integer reply, specifically:
|
* an integer greater than 0 if one or more keys were removed
|
* 0 if none of the specified key existed
|
*/
|
public static Long del(String key) {
|
Long result = null;
|
ShardedJedis client = getInstance();
|
try {
|
result = client.del(key);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
|
/**
|
* incrBy i(+i)
|
*
|
* @param key
|
* @param i
|
* @return new value after incr
|
*/
|
public static Long incrBy(String key, int i) {
|
Long result = null;
|
ShardedJedis client = getInstance();
|
try {
|
result = client.incrBy(key, i);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
|
/**
|
* exists valid
|
*
|
* @param key
|
* @return Boolean reply, true if the key exists, otherwise false
|
*/
|
public static boolean exists(String key) {
|
Boolean result = null;
|
ShardedJedis client = getInstance();
|
try {
|
result = client.exists(key);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
|
/**
|
* expire reset
|
*
|
* @param key
|
* @param seconds 存活时间,单位/秒
|
* @return Integer reply, specifically:
|
* 1: the timeout was set.
|
* 0: the timeout was not set since the key already has an associated timeout (versions lt 2.1.3), or the key does not exist.
|
*/
|
public static long expire(String key, int seconds) {
|
Long result = null;
|
ShardedJedis client = getInstance();
|
try {
|
result = client.expire(key, seconds);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
|
/**
|
* expire at unixTime
|
*
|
* @param key
|
* @param unixTime
|
* @return
|
*/
|
public static long expireAt(String key, long unixTime) {
|
Long result = null;
|
ShardedJedis client = getInstance();
|
try {
|
result = client.expireAt(key, unixTime);
|
} catch (Exception e) {
|
logger.error(e.getMessage(), e);
|
} finally {
|
if (client != null) {
|
client.close();
|
}
|
}
|
return result;
|
}
|
|
/**
|
* 实现redis keys 模糊查询
|
* @author hq
|
* @param pattern
|
* @return
|
*/
|
public static List<String> keys(String pattern){
|
logger.info("开始模糊查询【{}】keys", pattern);
|
ShardedJedis shardedJedis= shardedJedisPool.getResource();
|
Collection<Jedis> allShards = shardedJedis.getAllShards();
|
List<String> keyList = new ArrayList<>();
|
for(Jedis jedis:allShards){
|
Set<String> keys = jedis.keys(pattern);
|
keyList.addAll(keys);
|
}
|
logger.info("已获取所有keys");
|
return keyList;
|
}
|
|
public static void main(String[] args) {
|
//String SsoRedisAddress = "redis://域名:password@127.0.0.1:6379/0";
|
String SsoRedisAddress = "redis://127.0.0.1:6379/0";
|
init(SsoRedisAddress);
|
ShardedJedis client = getInstance();
|
client.set("cnblog", "cnblog");
|
client.set("redis", "redis");
|
client.set("test", "test");
|
client.set("123456", "1234567");
|
Client client1 = client.getShard("cnblog").getClient();
|
Client client2 = client.getShard("redis").getClient();
|
Client client3 = client.getShard("test").getClient();
|
Client client4 = client.getShard("123456").getClient();
|
|
////打印key在哪个server中
|
System.out.println("cnblog in server:" + client1.getHost() + " and port is:" + client1.getPort());
|
System.out.println("redis in server:" + client2.getHost() + " and port is:" + client2.getPort());
|
System.out.println("test in server:" + client3.getHost() + " and port is:" + client3.getPort());
|
System.out.println("123456 in server:" + client4.getHost() + " and port is:" + client4.getPort());
|
|
List<String> keys=keys("*session*");
|
keys.forEach(s->{
|
System.out.println(s);
|
});
|
}
|
|
}
|