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()); * 方式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 jedisShardInfos = new LinkedList(); 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 keys(String pattern){ logger.info("开始模糊查询【{}】keys", pattern); ShardedJedis shardedJedis= shardedJedisPool.getResource(); Collection allShards = shardedJedis.getAllShards(); List keyList = new ArrayList<>(); for(Jedis jedis:allShards){ Set 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 keys=keys("*session*"); keys.forEach(s->{ System.out.println(s); }); } }