Redis設置Key/value的規則定義和注意事項(附工具類)

對於redis的存儲key/value鍵值對,通過屢次踩坑以後,咱們總結了一套規則;這篇文章主要講解定義key/value鍵值對時的定義規則和注意事項。redis


前面一篇文章講了如何定義Redis的客戶端和Dubbo集成存儲器;當咱們真正開始開發的時候,就會忽然發現,有點不知道如何去定義Redis的Key和Value值格式,不要着急,立刻咱們就能夠明白如何去定義和使用,下面咱們開始講解如何定義。數據庫

Spring+Dubbo集成Redis的兩種解決方案json

一、redis value 值格式

在Java常規開發中,咱們須要有面向對象的思想,相對於對象來講,比較經常使用且能快速轉換的格式就是 JSON 了;比較經常使用的Java處理JSON數據有三個比較流行的類庫FastJSONGsonJackson,他們的優劣點這裏我就不一一介紹了,本文用阿里的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

zhangsan

上面咱們能夠看到在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值規則定義業務線文件夾。

json zhangsan

二、redis 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 常量類來實現,具體規則看我的愛好和需求。

結語

具體的定義規則工具類代碼都在上面了,也是源碼。

到此本文就結束了,關注公衆號查看更多推送!!!


關注個人公衆號
相關文章
相關標籤/搜索