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


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


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

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

1、redis value 值格式

在Java常規開發中,我們需要有面向對象的思想,相對於對象來說,比較常用且能快速轉換的格式就是 JSON 了;比較常用的Java處理JSON數據有三個比較流行的類庫FastJSONGsonJackson,他們的優劣點這里我就不一一介紹了,本文用阿里的FastJSON

上面提到了JSON,這是因為在Redis的存儲中,我們使用它來存儲value值,為什么要這樣做呢?主要是因為json格式有如下幾種好處:

· 1.標准,主流數據交換格式
· 2.簡單,結構清晰,相對於XML來說更加的輕量級,易於解析
· 3.語言無關,任何語言都能輕松搞它
· 4.類型安全,值是有類型的,比如整數、字符串、布爾等

下面我們來看看如何使用json來存儲value,代碼如下:


/**
 * 在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值的格式:

zhangsan

上面我們可以看到在redis可視化工具rdm(Redis Desktop Manager)中,key鍵對應的value用json非常清晰的顯示出來了,非常方便我們查閱redis中存儲的數據。

不知道大家注意到沒有,上面的代碼中有一行我是注釋掉了,代碼如下:

// String jKey = JSON.toJSONString(key);

這一行的意思是將key鍵也json化,不是說json非常友好嗎?那為什么要注釋這一行呢?下面為大家解釋為何要這樣做。

首先,使用json格式的數據都會變成一個josn格式的String字符串,比如 "zhangsan" ,當這個字符串作為key存儲時,默認會帶有json的特性,那就是雙引號 "" 也會帶入到redis的key設置中,所以在rdm中我們看到的key值都會默認帶上 "" ,這樣着實不是非常的美觀,特別是對於我們的復雜業務而言,后面會給大家講如何在rdm中使用key值規則定義業務線文件夾。

json zhangsan

2、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中以文件夾的形式分組查看,如圖:

冒號分組

3、使用枚舉類來定義規則

上面的工具類中的有如下代碼,使用了枚舉的形式來賦值:

/**
 * 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 常量類來實現,具體規則看個人愛好和需求。

結語

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

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


關注我的公眾號



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM