對於redis的存儲key/value鍵值對,通過屢次踩坑以後,咱們總結了一套規則;這篇文章主要講解定義key/value鍵值對時的定義規則和注意事項。redis
前面一篇文章講了如何定義Redis的客戶端和Dubbo集成存儲器;當咱們真正開始開發的時候,就會忽然發現,有點不知道如何去定義Redis的Key和Value值格式,不要着急,立刻咱們就能夠明白如何去定義和使用,下面咱們開始講解如何定義。數據庫
Spring+Dubbo集成Redis的兩種解決方案json
在Java常規開發中,咱們須要有面向對象的思想,相對於對象來講,比較經常使用且能快速轉換的格式就是 JSON
了;比較經常使用的Java處理JSON數據有三個比較流行的類庫FastJSON
、Gson
和Jackson
,他們的優劣點這裏我就不一一介紹了,本文用阿里的FastJSON
。緩存
上面提到了JSON
,這是由於在Redis的存儲中,咱們使用它來存儲value值,爲何要這樣作呢?主要是由於json格式有以下幾種好處:安全
· 1.標準,主流數據交換格式
· 2.簡單,結構清晰,相對於XML來講更加的輕量級,易於解析
· 3.語言無關,任何語言都能輕鬆搞它
· 4.類型安全,值是有類型的,好比整數、字符串、布爾等
複製代碼
下面咱們來看看如何使用json來存儲value,代碼以下:bash
/**
* 在redis數據庫中插入 key和value 而且設置過時時間
*
* @param key k
* @param value v
* @param exp 過時時間 s
* @return boolean
*/
@Override
public boolean set(String key, V value, int exp) {
Jedis jedis = null;
// 將 value 轉換成 json 對象
// String jKey = JSON.toJSONString(key);
String jValue = JSON.toJSONString(value);
// 操做是否成功
boolean isSucess = true;
if (StringUtils.isEmpty(key)) {
LOG.info("key is empty");
return false;
}
try {
// 獲取客戶端對象
jedis = redisCache.getResource();
// 執行插入
jedis.setex(key, exp, jValue);
} catch (Exception e) {
LOG.info("client can't connect server");
isSucess = false;
if (null != jedis) {
// 釋放jedis對象
redisCache.brokenResource(jedis);
}
return false;
} finally {
if (isSucess) {
// 返還鏈接池
redisCache.returnResource(jedis);
}
}
return true;
}
複製代碼
代碼中redis value在存儲前咱們對其作了一次轉換,將對象V轉換爲json對象後存儲;下面咱們來看看在redis中value值的格式:app
上面咱們能夠看到在redis可視化工具rdm(Redis Desktop Manager)中,key鍵對應的value用json很是清晰的顯示出來了,很是方便咱們查閱redis中存儲的數據。ide
不知道你們注意到沒有,上面的代碼中有一行我是註釋掉了,代碼以下:工具
// String jKey = JSON.toJSONString(key);
複製代碼
這一行的意思是將key鍵也json化,不是說json很是友好嗎?那爲何要註釋這一行呢?下面爲你們解釋爲什麼要這樣作。ui
首先,使用json格式的數據都會變成一個josn格式的String字符串,好比 "zhangsan"
,當這個字符串做爲key存儲時,默認會帶有json的特性,那就是雙引號 ""
也會帶入到redis的key設置中,因此在rdm中咱們看到的key值都會默認帶上 ""
,這樣着實不是很是的美觀,特別是對於咱們的複雜業務而言,後面會給你們講如何在rdm中使用key值規則定義業務線文件夾。
上面講了簡單的key存儲,如 zhangsan
的存儲,此時普通的需求能夠知足;然而在實際業務中,每每key鍵的存儲會很是的複雜,好比咱們如今有一個需求:
需求:根據基礎數據系統中的數據字典類型查詢對應的字典集合
複製代碼
這時,咱們須要關注的業務就變得複雜了,就不能使用常規的key鍵存儲方式,上面的需求大體能夠拆分爲:
1.系統:基礎數據系統
2.模塊:數據字典
3.方法:根據數據字典類型查詢
4.參數:字典類型
複製代碼
爲何要這樣拆分呢?爲了可讀性;也爲了抽象出key存儲規則;由於業務複雜狀況下,咱們定義的key鍵太多時就不便於管理,也不便於查找,以 系統-模塊-方法-參數
這樣的規則定義,咱們能夠很清晰的瞭解redis key存儲的值是作了什麼事情,並且rdm中也能夠以此來分組,後面會講到。
下面貼上根據此規則定義抽象出的redis工具類:
package com.yclimb.mdm.redis;
/**
* Redis 工具類
*
* @author yclimb
* @date 2018/4/19
*/
public class RedisUtils {
/**
* 主數據系統標識
*/
public static final String KEY_PREFIX = "mdm";
/**
* 分割字符,默認[:],使用:可用於rdm分組查看
*/
private static final String KEY_SPLIT_CHAR = ":";
/**
* redis的key鍵規則定義
* @param module 模塊名稱
* @param func 方法名稱
* @param args 參數..
* @return key
*/
public static String keyBuilder(String module, String func, String... args) {
return keyBuilder(null, module, func, args);
}
/**
* redis的key鍵規則定義
* @param module 模塊名稱
* @param func 方法名稱
* @param objStr 對象.toString()
* @return key
*/
public static String keyBuilder(String module, String func, String objStr) {
return keyBuilder(null, module, func, new String[]{objStr});
}
/**
* redis的key鍵規則定義
* @param prefix 項目前綴
* @param module 模塊名稱
* @param func 方法名稱
* @param objStr 對象.toString()
* @return key
*/
public static String keyBuilder(String prefix, String module, String func, String objStr) {
return keyBuilder(prefix, module, func, new String[]{objStr});
}
/**
* redis的key鍵規則定義
* @param prefix 項目前綴
* @param module 模塊名稱
* @param func 方法名稱
* @param args 參數..
* @return key
*/
public static String keyBuilder(String prefix, String module, String func, String... args) {
// 項目前綴
if (prefix == null) {
prefix = KEY_PREFIX;
}
StringBuilder key = new StringBuilder(prefix);
// KEY_SPLIT_CHAR 爲分割字符
key.append(KEY_SPLIT_CHAR).append(module).append(KEY_SPLIT_CHAR).append(func);
for (String arg : args) {
key.append(KEY_SPLIT_CHAR).append(arg);
}
return key.toString();
}
/**
* redis的key鍵規則定義
* @param redisEnum 枚舉對象
* @param objStr 對象.toString()
* @return key
*/
public static String keyBuilder(RedisEnum redisEnum, String objStr) {
return keyBuilder(redisEnum.getKeyPrefix(), redisEnum.getModule(), redisEnum.getFunc(), objStr);
}
}
複製代碼
上面代碼中有此文字描述 分割字符,默認[:],使用:可用於rdm分組查看
;redis key默認使用冒號分割,好處在於能夠在rdm中以文件夾的形式分組查看,如圖:
上面的工具類中的有以下代碼,使用了枚舉的形式來賦值:
/**
* redis的key鍵規則定義
* @param redisEnum 枚舉對象
* @param objStr 對象.toString()
* @return key
*/
public static String keyBuilder(RedisEnum redisEnum, String objStr) {
return keyBuilder(redisEnum.getKeyPrefix(), redisEnum.getModule(), redisEnum.getFunc(), objStr);
}
複製代碼
下面是枚舉類代碼:
package com.yclimb.mdm.redis;
/**
* Redis 枚舉類
*
* @author yclimb
* @date 2018/4/19
*/
public enum RedisEnum {
/**
* 數據字典Service - 根據字典類型查詢字典數據
*/
MDM_MSTDATADICTIONARYSERVICE_QUERYLISTBYENTITYREDIS(
RedisUtils.KEY_PREFIX, "MstDataDictionaryService", "queryListByEntityRedis", "數據字典Redis緩存");
/**
* 系統標識
*/
private String keyPrefix;
/**
* 模塊名稱
*/
private String module;
/**
* 方法名稱
*/
private String func;
/**
* 描述
*/
private String remark;
RedisEnum(String keyPrefix, String module, String func, String remark) {
this.keyPrefix = keyPrefix;
this.module = module;
this.func = func;
this.remark = remark;
}
getter and setter....
}
複製代碼
使用上面的枚舉類,能夠根據模塊和方法定義須要的枚舉類型,便於管理和維護,使用起來也很是方便,使用代碼以下:
@Override
public List<MstDataDictionary> queryListByEntityRedis(MstDataDictionary mstDataDictionary) {
// redis key 獲取
String redisKey = RedisUtils.keyBuilder(RedisEnum.MDM_MSTDATADICTIONARYSERVICE_QUERYLISTBYENTITYREDIS, (null == mstDataDictionary ? "" : mstDataDictionary.toString()));
// 查詢redis緩存
List<MstDataDictionary> mstDataDictionaryList = (List<MstDataDictionary>) redisCacheService.get(redisKey);
// 若是沒有緩存則查詢數據庫後賦值
if (mstDataDictionaryList == null || mstDataDictionaryList.size() <= 0) {
mstDataDictionaryList = mstDataDictionaryMapper.queryListByEntity(mstDataDictionary);
redisCacheService.set(redisKey, mstDataDictionaryList);
}
return mstDataDictionaryList;
}
複製代碼
OK,到這裏就差很少講完了,根據上面所說的分模塊方式,自定義redis的key鍵名稱,value值格式使用json來存儲;
對於key鍵的規則定義也可使用 Constants
常量類來實現,具體規則看我的愛好和需求。
具體的定義規則工具類代碼都在上面了,也是源碼。
到此本文就結束了,關注公衆號查看更多推送!!!