redis数据结构缓存运用
- - 企业架构 - ITeye博客之前redis已经描述了redis 的基本作用与用处, 这一篇主要讲述redis运用场景以及分片,和spring整合. redis 存储数据结构大致5种,String 普通键值对,用的比较多. HASH针对 key 唯一标识 hashmap 键值对运用也比较多 list set 当然是集合运用 sortedSet 排序集合使用.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="order" value="2" /> <property name="ignoreUnresolvablePlaceholders" value="true" /> <property name="locations"> <list> <value>classpath:demo-provider-module.properties</value> </list> </property> </bean> <!-- redis连接池的配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="2048" /> <property name="maxIdle" value="200" /> <property name="numTestsPerEvictionRun" value="1024"/> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <property name="minEvictableIdleTimeMillis" value="-1" /> <property name="softMinEvictableIdleTimeMillis" value="10000" /> <property name="maxWaitMillis" value="1500"/> <property name="testOnBorrow" value="true" /> <property name="testWhileIdle" value="true"/> <property name="testOnReturn" value="false"/> <property name="jmxEnabled" value="true"/> <property name="jmxNamePrefix" value="youyuan"/> <property name="blockWhenExhausted" value="false"/> </bean> <!-- redis的连接池pool,不是必选项:timeout/password --> <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"> <constructor-arg index="0" ref="jedisPoolConfig"/> <constructor-arg index="1"> <list> <bean name="master" class="redis.clients.jedis.JedisShardInfo"> <constructor-arg index="0" value="${redis1.server.host}"/> <constructor-arg index="1" value="${redis1.server.port}" type="int"/><!-- 指定参数类型否则可能回报错 --> <constructor-arg index="2" value="${redis1.server.timeout}" type="int"/> </bean> </list> </constructor-arg> </bean> </beans>
package demo.dcn.cache; import java.util.ArrayList; import java.util.List; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.google.protobuf.Internal.ProtobufList; /** * Redis序列化及反序列化工具类 * @author [email protected] */ public class JedisUtil { /** * 把对象转换成json 文本 * @param object * @return */ public static String toJson(Object object){ return JSON.toJSONString(object); } /** * 单独的T 代表一个类型 而 Class<T>代表这个类型所对应的类 * 把JSON文本parse为JavaBean * @param json * @param clazz * @return */ public static <T> T toObject(String json,Class<T> clazz){ return JSON.parseObject(json, clazz); } /** * 泛型解析方法 * * @param json * @param typeReference * @return */ public static <T> T toObject(String json,TypeReference<T> typeReference){ return JSON.parseObject(json, typeReference); } /** * 把json 文本转换成对象集合形式 * @param json * @param T * @return */ public static <T> List<T> parseArray(String json,Class<T> T){ return JSON.parseArray(json, T); } /** * 解析数组json 转换成对象集合方式 * @param jsons * @param clazz * @return */ public static <T> List<T> toObjects(List<String> jsons, Class<T> clazz){ List<T> list = new ArrayList<T>(); for (String json : jsons) { T obj = toObject(json, clazz); if(null != obj) { list.add(obj); } } return list; } /** * 把把JSON文本parse为JSONObject javamap或者JSONArray Javalist * @param json * @return */ public static Object parseObject(String json){ return JSON.parse(json); } /** * 把JSON文本parse成JSONObject * @param json * @return */ public static JSONObject parJsonObject(String json){ return JSONObject.parseObject(json); } /** * 把JSON文本parse成JSONArray * @param text * @return */ public static final JSONArray parseArray(String text){ return JSONArray.parseArray(text); } /** * 将JavaBean序列化为带格式的JSON文本 * @param object * @param prettyFormat * @return */ public static final String toJSONString(Object object, boolean prettyFormat){ return JSON.toJSONString(object, prettyFormat); } /** * 将JavaBean转换为JSONObject或者JSONArray * @param javaObject * @return */ public static final Object toJSON(Object javaObject){ return JSON.toJSON(javaObject); } }
package demo.dcn.cache; import redis.clients.jedis.ShardedJedis; /** * 自定义分片jedis * @author [email protected] */ public class SelfShardedJedis { private ShardedJedis shardedJedis;//分片 private Boolean isReturn;//是否归还连接池 public SelfShardedJedis(ShardedJedis shardedJedis, Boolean isReturn) { super(); this.shardedJedis = shardedJedis; this.isReturn = isReturn; } public SelfShardedJedis() { super(); } /** * @return the shardedJedis */ public ShardedJedis getShardedJedis() { return shardedJedis; } /** * @param shardedJedis the shardedJedis to set */ public void setShardedJedis(ShardedJedis shardedJedis) { this.shardedJedis = shardedJedis; } /** * @return the isReturn */ public Boolean getIsReturn() { return isReturn; } /** * @param isReturn the isReturn to set */ public void setIsReturn(Boolean isReturn) { this.isReturn = isReturn; } }
package demo.dcn.cache; import java.util.Set; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisShardInfo; import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedisPool; public class RedisClientBase implements RedisClient { private final Logger logger = LoggerFactory.getLogger(RedisClientBase.class); private static final String NX ="NX";//redis 设置key不存在时候起作用 private static final String XX = "XX";//redis 设置key存在 ,才能对键进行操作 private static final String EX ="EX";//redis 设置键固定时间秒 private static final String PX ="PX";//redis 设置键固定时间毫秒 @Resource private ShardedJedisPool shardedJedisPool;//连接池 public static final int MAX_SCAN_COUNT = 200; private static RedisClient redisclient; public RedisClientBase(ShardedJedisPool shardedJedisPool) { super(); this.shardedJedisPool = shardedJedisPool; } public RedisClientBase() { redisclient = this; } public static RedisClient getInstance() { return redisclient; } /** * 获取一个分片 jedis 客户端 * * @return */ public SelfShardedJedis getShardedJedis(){ ShardedJedis shards = shardedJedisPool.getResource(); SelfShardedJedis selfShardedJedis = new SelfShardedJedis(shards, false); return selfShardedJedis; } /** * 关闭 jedis 切片池 * @param jedis * @param broken */ @SuppressWarnings({ "null", "deprecation" }) public void closeRedisThread(SelfShardedJedis jedis, boolean broken){ try{ if(jedis!=null||jedis.getIsReturn()){ return; } if(broken){ shardedJedisPool.returnBrokenResource(jedis.getShardedJedis()); jedis.setIsReturn(true); }else{ shardedJedisPool.returnResource(jedis.getShardedJedis()); jedis.setIsReturn(true); } }catch(Exception e){ logger.error(e.getMessage(),e); } } /**setnx 的值设为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则 setNotExists 不做任何动作。 * 保存 * @param key * @param obj * @return * 设置成功,返回 1 ;设置失败,返回 0 。 */ public Long setNotExists(String key,byte[] obj){ SelfShardedJedis shardedJedis = null; boolean broken = false; try{ shardedJedis = getShardedJedis(); return shardedJedis.getShardedJedis().setnx(key.getBytes(), obj);//保存成二进制 }catch(Exception e){ logger.error(e.getMessage(), e); broken = true; }finally{ closeRedisThread(shardedJedis, broken); } return 0L; } /** * 将 key 的值设为 value ,且设置过期时间,当且仅当 key 不存在。 若给定的 key 已经存在,则 setNotExists 不做任何动作。 * Set the string value as value of the key. The string * can't be longer than 1073741824 bytes (1 GB). * @param key * @param value * @param nxxx * @param expx * @param time * @return */ public String set(String key,String value, String nxxx, String expx, long time){ SelfShardedJedis shardedJedis = null; boolean broken = false; try{ shardedJedis = getShardedJedis(); return shardedJedis.getShardedJedis().set(key, value, nxxx, expx, time); }catch(Exception e){ logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 通过key 获取字符串数据 * @param key * @return */ public String getString(String key){ SelfShardedJedis shardedJedis = null; boolean broken = false; try{ shardedJedis = getShardedJedis(); return shardedJedis.getShardedJedis().get(key); }catch(Exception e){ logger.error(e.getMessage(), e); broken = true; }finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 设置key过期时间 * @param key * @param obj * @param expireTime * @return */ public String setExpire(String key, byte[] obj, int expireTime) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); return shardedJedis.getShardedJedis().setex(key.getBytes(), expireTime, obj); } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 设置key过期时间 * @param key * @param expireTime * @return */ public Long expire(String key, int expireTime) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); return shardedJedis.getShardedJedis().expire(key, expireTime); } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 移除有序集 key 中,指定排名(rank)区间内的所有成员。 * <p/> * 区间分别以下标参数 start 和 stop 指出,包含 start 和 stop 在内。 下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。 你也可以使用负数下标,以 -1 * 表示最后一个成员, -2 表示倒数第二个成员,以此类推 * * @param key * @param start * @param stop * @return */ public Long zremrangeByRank(String key, long start, long stop) { long result = 0L; SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); result = shardedJedis.getShardedJedis().zremrangeByRank(key, start, start); } catch (Exception e) { broken = true; logger.error(e.getMessage(), e); } finally { closeRedisThread(shardedJedis, broken); } return result; } /** * 返回有序集 key 中,指定区间内的成员 其中成员的位置按 score 值递减(从大到小)来排列 * * @param key * @param start * @param stop * @return */ public Set<String> zrevrange(String key, long start, long stop) { Set<String> result = null; SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); result = shardedJedis.getShardedJedis().zrevrange(key, start, start); } catch (Exception e) { broken = true; logger.error(e.getMessage(), e); } finally { closeRedisThread(shardedJedis, broken); } return result; } /** * 删除key * @param key * @return */ public Long del(String key) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); return shardedJedis.getShardedJedis().del(key); } catch (Exception e) { broken = true; logger.error(e.getMessage(), e); } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 计数器 * * @param key * @param seconds 过期时间长度,单位:秒;值为0或负数表示不过期。 * @param roll 时间是否滚动 */ public Long incr(String key, int seconds, boolean roll) { long b = 0; SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); b = shardedJedis.getShardedJedis().incr(key.getBytes()); if (seconds > 0) { if (b == 1) {// 第一次进入,设置过期时间 shardedJedis.getShardedJedis().expire(key.getBytes(), seconds); } if (roll && b > 1) {// 时间滚动 shardedJedis.getShardedJedis().expire(key.getBytes(), seconds); } } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { if (broken && shardedJedis != null) { shardedJedis.getShardedJedis().del(key); } closeRedisThread(shardedJedis, broken); } return b; } /** * 判断key 是否存在 * @param key * @return若 */ public Boolean exists(String key) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); return shardedJedis.getShardedJedis().exists(key.getBytes()); } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return false; } /** * 通过key 获取 jedis * @param key * @return */ public Jedis getShard(String key) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().getShard(key); } } catch (Exception e) { e.printStackTrace(); logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 获取JedisShardInfo * * @param key * @return JedisShareInfo */ public JedisShardInfo getShardInfo(String key) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().getShardInfo(key); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 保存字符串键值对 * @param key * @param value * @return */ public String set(String key, String value) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().set(key, value); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 获取key的类型 * @param key * @return */ public String type(String key) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().type(key); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 获取key 剩余时间 当 key 不存在时,返回 -2 。 * 当 key 存在但没有设置剩余生存时间时,返回 -1 。 * 否则,以秒为单位,返回 key 的剩余生存时间。 * @param key * @return */ public Long ttl(String key) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().ttl(key); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 为key 设定一个新值,并返回旧值 * 返回给定 key 的旧值。 * 当 key 没有旧值时,也即是, key 不存在时,返回 nil 。 不是字符串类型返回错误 * @param key * @param value * @return */ public String getSet(String key, String value) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().getSet(key, value); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 当key 不存在时候 保存key String类型 存在不做什么操作返回0 * @param key * @param value * @return */ public Long setnx(String key, String value) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().setnx(key, value); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 设置key 存在修改,不存在保存 * @param key * @param seconds * @param value * @return */ public String setex(String key, int seconds, String value) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().setex(key, seconds, value); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 对指定的key 进行减少 如果key 不存在 key值会被初始化0 然后减少 * @param key * @param integer * @return */ public Long decrBy(String key, long integer) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().decrBy(key, integer); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 如果key 按指定增量增加 key 不存在 创造key 初始化为0 incr 自增为1 * @param key * @param integer * @return */ public Long incrBy(String key, long integer) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().incrBy(key, integer); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 为已经存在的key追加新值,返回 长度 如果key 不存在,直接设置key为value * @param key * @param value * @return */ public Long append(String key, String value) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().append(key, value); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } /** * 截取字符串 * @param key * @param start * @param end * @return */ public String substr(String key, int start, int end) { SelfShardedJedis shardedJedis = null; boolean broken = false; try { shardedJedis = getShardedJedis(); if (shardedJedis != null) { return shardedJedis.getShardedJedis().substr(key, start, end); } } catch (Exception e) { logger.error(e.getMessage(), e); broken = true; } finally { closeRedisThread(shardedJedis, broken); } return null; } }