Redis 设置 Key/value 的规则定义和注意事项(附工具类)

栏目: 数据库 · 发布时间: 7年前

内容简介:对于redis的存储key/value键值对,经过多次踩坑之后,我们总结了一套规则;这篇文章主要讲解定义key/value键值对时的定义规则和注意事项。前面一篇文章讲了如何定义Redis的客户端和Dubbo集成存储器;当我们真正开始开发的时候,就会突然发现,有点不知道如何去定义Redis的Key和Value值格式,不要着急,马上我们就可以明白如何去定义和使用,下面我们开始讲解如何定义。Spring+Dubbo集成Redis的两种解决方案

对于 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值的格式:

Redis 设置 Key/value 的规则定义和注意事项(附 <a href='https://www.codercto.com/tool.html'>工具</a> 类)

上面我们可以看到在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值规则定义业务线文件夹。

Redis 设置 Key/value 的规则定义和注意事项(附工具类)

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中以文件夹的形式分组查看,如图:

Redis 设置 Key/value 的规则定义和注意事项(附工具类)

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 常量类来实现,具体规则看个人爱好和需求。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Discrete Mathematics and Its Applications

Discrete Mathematics and Its Applications

Kenneth H Rosen / McGraw-Hill Science/Engineering/Math / 2003-04-22 / USD 132.81

Discrete Mathematics and its Applications is a focused introduction to the primary themes in a discrete mathematics course, as introduced through extensive applications, expansive discussion, and deta......一起来看看 《Discrete Mathematics and Its Applications》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具