多個redis有序集合組合如何?分頁
需求:現在將不同類別的資料放入不同的redis有序集合key中,查詢的時候不區分類別,進行統一的查詢。
redis分頁實體:
import java.io.Serializable;/** * 中間過濾實體<br> * 〈功能詳細描述〉 * * @author wangmuming * @see [相關類/方法](可選) * @since [產品/模組版本] (可選) */public class RedisPaging implements Serializable { /** */ private static final long serialVersionUID = 8028303213452701294L; private String key; private long total; private int offset; private int limit; /** * @return the key */ public String getKey() { return key; } /** * @param key the key to set */ public void setKey(String key) { this.key = key; } /** * @return the total */ public long getTotal() { return total; } /** * @param total the total to set */ public void setTotal(long total) { this.total = total; } /** * @return the offset */ public int getOffset() { return offset; } /** * @param offset the offset to set */ public void setOffset(int offset) { this.offset = offset; } /** * @return the limit */ public int getLimit() { return limit; } /** * @param limit the limit to set */ public void setLimit(int limit) { this.limit = limit; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "RedisPaging [key=" + key + ", total=" + total + ", offset=" + offset + ", limit=" + limit + "]"; } }
查詢方法內的內容:
//使用linkedhashmap 作為有序集合返回json Map<String,Object> map = new LinkedHashMap<String,Object>(); map.put("start", page); map.put("draw", draw); try { String[] keys = key.split(","); if( keys.length == 1 ) { // 擷取redis 統計資訊 long total = RedisUtil.zcard(key); int offset = page; //分頁從0開始// long pagesize = (total % count) == 0 ? total /count : (total /count)+1; if(offset <= total) { List<String> list = RedisUtil.zrangeByScore(key, sort, offset, count); List<OrderlinkAlert> objList = new ArrayList<OrderlinkAlert>(); OrderlinkAlert obj = null; long index = offset + 1l; for (String string : list) { obj = new OrderlinkAlert(); obj.setId(index); obj.setOrderItemId(string); Double time = RedisUtil.zscore(key, string); long efficateTime = 0l; if( null != time ) { efficateTime = time.longValue(); } obj.setExceedRange(DateUtil.formatTime(efficateTime)); objList.add(obj); index++; } map.put("data", objList); map.put("recordsTotal", total); map.put("recordsFiltered", total); //map.put("page", pagesize); map.put("length", count); } } else { //並行路徑的請求情況 // 擷取redis 統計資訊 long total = 0l; //將多個key值從儲存到list中 List<RedisPaging> keyList = new ArrayList<RedisPaging>(); RedisPaging paging = null; for (String string : keys) { long tmp = RedisUtil.zcard(string); total = total + tmp; paging = new RedisPaging(); paging.setKey(string); paging.setTotal(tmp); keyList.add(paging); } int offset = page; //分頁從0開始// long pagesize = (total % count) == 0 ? total /count : (total /count)+1; if(offset <= total) { //計算每個key裡面去哪些資料 keyList = computeRedisPaging(keyList,offset,count,total); Map<String,String> mapping = new LinkedHashMap<String,String>(); // 多個key值存在的邏輯 for (RedisPaging redisPaging : keyList) { List<String> list = RedisUtil.zrangeByScore(redisPaging.getKey(), sort, redisPaging.getOffset(), redisPaging.getLimit()); if( null != list && !list.isEmpty() ) { for (String string : list) { Double time = RedisUtil.zscore(redisPaging.getKey(), string); long efficateTime = 0l; if( null != time ) { efficateTime = time.longValue(); } mapping.put(string, DateUtil.formatTime(efficateTime)); } } } List<OrderlinkAlert> objList = new ArrayList<OrderlinkAlert>(); OrderlinkAlert obj = null; long index = offset + 1l; for (Map.Entry<String,String> entity : mapping.entrySet()) { obj = new OrderlinkAlert(); obj.setId(index); obj.setOrderItemId(entity.getKey()); obj.setExceedRange(entity.getValue()); objList.add(obj); index++; } map.put("data", objList); map.put("recordsTotal", total); map.put("recordsFiltered", total); //map.put("page", pagesize); map.put("length", count); } } } catch (Exception e) { logger.error("query redis data error:", e); throw new Exception(e); }
redis 多有序集合分頁邏輯的實現:
private List<RedisPaging> computeRedisPaging(List<RedisPaging> keyList, int offset, int count, long total) { //當前需要擷取的記錄數 long sum = 0; int indexStart = 0; int indexEnd = 0; //計算出兩個值 大於 等於 offset 小於等於 offset + count+1的位置 for(int i=0;i<keyList.size();i++) { sum = sum + keyList.get(i).getTotal(); if( sum >= (offset) ) { indexStart = i; break; } } sum = 0; for(int i=0;i<keyList.size();i++) { sum = sum + keyList.get(i).getTotal(); if( i >= indexStart && sum >= (offset+count) ) { indexEnd = i; break; } else if (i >= indexStart && i == (keyList.size()-1) && sum >= offset && sum <= (offset+count)) { indexEnd = i; break; } } // System.out.println("indexStart :"+indexStart + " indexEnd :"+ indexEnd); //如果只存在一個 取全部資料 if( indexStart == indexEnd ) { RedisPaging paging = keyList.get(indexStart); long t = 0l; for(int i=0;i<indexStart;i++) { t = t + keyList.get(i).getTotal(); } paging.setOffset(offset-(int)t); paging.setLimit(count); keyList.clear(); keyList.add(paging); } //如果只存在2個 分開去資料 計算第一個 - offset 從第二個裡面補剩下的資料 if( (indexEnd-indexStart) == 1 ) { RedisPaging paging0 = keyList.get(indexStart); long t = 0l; for(int i=0;i<indexStart;i++) { t = t + keyList.get(i).getTotal(); } long rest0 = offset - t; paging0.setOffset((int)rest0); paging0.setLimit((int) (paging0.getTotal()-rest0)); RedisPaging paging1 = keyList.get(indexEnd); paging1.setOffset(0); paging1.setLimit((int) (count-(paging0.getTotal()-rest0))); keyList.clear(); if( paging0.getTotal() > 0 ) { keyList.add(paging0); } if( paging1.getTotal() >0 ) { keyList.add(paging1); } } //如果大於等於3 中間的去所有的 開頭 和 結束 計算取多少 if( (indexEnd-indexStart) >= 2 ) { List<RedisPaging> tmp = new ArrayList<RedisPaging>(); tmp.addAll(keyList); keyList.clear(); long t = 0l; for(int i=0;i<indexStart;i++) { t = t + tmp.get(i).getTotal(); } long rest0 = offset - t; RedisPaging pagingStart = tmp.get(indexStart); pagingStart.setOffset((int)rest0); pagingStart.setLimit((int) (pagingStart.getTotal() - rest0 )); if (pagingStart.getTotal() > 0 ) { keyList.add(pagingStart); } rest0 = pagingStart.getTotal() - rest0 ; for(int i=(indexStart+1);i<indexEnd;i++) { RedisPaging paging = tmp.get(i); paging.setOffset(0); paging.setLimit((int)tmp.get(i).getTotal()); rest0 = rest0 + tmp.get(i).getTotal(); if (paging.getTotal() > 0 ) { keyList.add(paging); } } RedisPaging pagingTop = tmp.get(indexEnd); pagingTop.setOffset(0); pagingTop.setLimit((int) (count-rest0)); if (pagingTop.getTotal() > 0 ) { keyList.add(pagingTop); } } return keyList; }