封装redis缓存,并实现,精准查询及分页查询

​使用方式及代码

//查询 某条记录表名 ts =  表名Cache.getValue(表名Cache.getEndkey(), datatype + "_" + number);

//清除缓存

表名Cache.delete(null, 表名Cache.cacheName(ts));

//分页查询

List<Object> list = null;

if ("desc".equals(sort)){

list = productonuserCache.userQueryBySort(productonuserCache.getEndkey(), userId, 1 , page, size);

}else{

list = productonuserCache.userQueryBySort(productonuserCache.getEndkey(), userId, 0 , page, size);

}

Long total = productonuserCache.getTotal(productonuserCache.getEndkey(),userId);

 

 

// 每张表需要多个字段查询的时候,需要实现多个 缓存类。 

例如。  表名字段名Cache

@Override

public String cacheName(表名 v) {

return v.getDatatype()+"_"+v.get字段名();

}

 

——————

 

 

1、利用泛型及抽象类,使用者来实现主要的数据加载部分方法。

好处是,用户简单实现无逻辑,不容易出错。 

public abstract class CacheTools<V> {

/**

* 加载数据

* @param userId

* @return

*/

public abstract List<V> getAllData(String userId);

/**

* 排序字段

* @param v

* @return

*/

public abstract double getScore(V v) ;

/**

* redis key 的组成 hash 集合存放的主键。例如: 订单,就是 ordercode  

* @param v

* @return

*/

public abstract String cacheName(V v);

 

public abstract V findDbOne(String key, String userId);

 

/**

* 缓存名称,一般使用表名

* @return

*/

public abstract String getEndkey();

}

2、更新缓存

/**

* 添加或更新

* @param tmp

* @return

*/

public V save(String userId,V v) {

if (v == null){

log.error("{m:CacheTools.save,msg: v==null}---");

return v;

}else{

String key = getEndkey();

String endkey = joinKey(key, userId);

modifiedCount(endkey);

ZSetOperations<String, String> zset = getRedisService().getZsetOper();

return saveOne(endkey, zset, v);

}

 

}

 

/**

* 批量添加或更新  不能用于加载。 

* @param userId

* @param tmp

* @return

*/

public Iterable<V> save(String userId, Iterable<V> tmp) {

log.info(" {Cachetools save }: "+userId + tmp);

ZSetOperations<String, String> zset = getRedisService().getZsetOper();

tmp.forEach((V v)->{

saveOne(joinKey(getEndkey(), userId), zset, v);

});

return tmp;

}

3、删除缓存

public void delete(String userId, Object... values){

log.info("{cacheTools}:delete"+userId + values);

String key = getEndkey();

String endkey = joinKey(key, userId);

modifiedCount(endkey);

log.info("-------------CacheTools: delete: "+joinHashKey(endkey)+ " values"+values);

 

getRedisService().hremoveKey(joinHashKey(endkey), values);

if(loadSortFlag){

log.info("{ cache tools } delete :"+values + " "+userId);

ZSetOperations<String, String> zset = getRedisService().getZsetOper();

zset.remove(joinZsetKey(endkey), values);

}

4、精确定位查询

public V getCacheValue(String key,String userId ,String cachename, RedisService rs){

V val = (V)rs.hget(joinHashKey(joinKey(key, userId)), cachename);

if (val == null){

// 2019 03 05 解决,只想加载当前查询内容的情况。不考虑多加载,也不考虑用户纬度。

if (onlyLoadCurrentFlag){

val = findDbOne(cachename,userId);

save(userId, val);

}else{

if (enabledLoad( key, userId, rs )){

val = (V)rs.hget(joinHashKey(joinKey(key, userId)), cachename);

log.info(" 阻塞加载后获取内容:"+key + " "+ userId+" "+val);

return val;

};

}

}

return val;

 

}

5、查询总数

/**

* 查询数据总数

* @param string

* @param userId

* @return

*/

public Long getTotal(String key, String userId) {

ZSetOperations<String, String> zset = getRedisService().getZsetOper();

return zset.size(joinZsetKey(joinKey(key,userId)));

}

6、分页查询实现

/**

* 倒序分页查询,用户自己内容,这个部分属于活跃的占少数,所以采用不欲缓存, 并且采用加失效时间。 

* @param userId

* @param sort 1 倒序

* @param page

* @param size

* @return

*/

public List<Object> userQueryBySort(String key ,String userId,int sort , int page, int size) {

log.info("{cache}:userQueryBySort"+key+userId);

//维护用户活跃度

refreshUser(userId);

List <Object> list = query(sort, page, size, joinKey(key, userId));

if (list == null || list.size() <=0 ){

log.info("{缓存未查询到内容}"+userId + " "+ key);

if (enabledLoad( key, userId, getRedisService() )){

list = query(sort, page, size, joinKey(key, userId));

log.info("querybysort- 阻塞加载后获取内容:"+key + " "+ userId+" "+list);

return list;

}

}else{

log.info("query by sort {缓存被发现:}"+list.size());

}

return list;

}

/**

* 分页查询

* @param key

* @param sort 1 倒序

* @param page

* @param size

* @return

*/

public List<Object> queryBySort(String key , int sort ,int page, int size) {

return query(sort, page, size, key);

}

 

private List<Object> query(int sort, int page, int size, String endkey) {

log.info("{cache}:query"+endkey);

page = page <= 0 ? 1:page;

ZSetOperations<String, String> zset = getRedisService().getZsetOper();

 

Set <String> keys = null;

if (1 == sort){

keys = zset.reverseRange(joinZsetKey(endkey), ( page - 1 ) * size, page * size - 1);

}else{

keys = zset.range(joinZsetKey(endkey), ( page - 1 ) * size, page * size - 1);

}

log.info("query:size :"+keys.size());

List tmp =  getRedisService().hmget(joinHashKey(endkey), keys);

log.info("query:list"+tmp.size());

return tmp;

}

7、实现方式

组件使用方式

import com.mini.openec.utils.CacheTools;

@Service

public class 表名Cache extends CacheTools<表名>{

private final Log log = LogFactory.getLog(表名Cache.class);

public 表名Cache() {

                 /* 参数说明,

boolean loadActiveUserFlag,  

= true 自动缓存 10天内活跃用户的本表内容 

      = false 自动缓存 表的全部数据,如果无此需求,只要在getAllData 方法返回null 即可不自动缓存全部内容

boolean loadSortFlag ,

= true 生成分页缓存,可以分页查询

= false 不生成分页缓存,不能分页查询

boolean onlyLoadCurrentFlag

= true 只加载当前内容,如与用户无关,userId 传null

= false 按前两个参数加载。

*/

init(false, false, true); // 只缓存当前值

}

 

@Override

public String cacheName(表名 v) {

return v.getDatatype()+"_"+v.getNumber();

}

@Override

public List<表名> getAllData(String userId) {

return null;//表名Service.listAll();

}

@Override

public double getScore(表名 v) {

return v.getCode().hashCode();

}

@Override

public String getEndkey() {

return "表名";

}

@Override

public 表名 findDbOne(String key,String userId) {

if (StringUtils.isNotEmpty(key)){

String strs[] = key.split("_");

if (strs.length >= 2){

log.info("{key:"+strs[1]+",old:"+key+"}");

return 表名Service.findByNumber(strs[1]);

}

}

return null;

 

}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值