Redis hash 是一个 string 类型的 field 和 value 的映射表,当然这里的string类型是指将数据序列化后的字符串。
常见业务场景就是来缓存键值对。我举个例子,有一个班级里有三十个学生,每个学生都有唯一的学号,那么就能够使用Redis的hash进行存储。班级作为标识这些学生一个共性(key),也就是说可以通过这个班级来找到这群学生。在这群学生里面,每个学生(value)又有唯一的一个标识,例如学号(field)来区分他们。
数据结构: key班级 ------ field 学号 ----- value 具体学生
因此,立刻想到使用Hash缓存的心法:有一个能够筛选出一组数据的标识key。在这组被筛选出来的数据中,每个数据自身又有一个唯一的标识符field,以此来标识它value。有着这类特点的数据,可以使用Redis的hash作为缓存。
常见业务场景
(一)缓存字典表。一个简单的字典表,参照下图。type字段作为key, code字段作为field,对应的记录们作为value。
(二)缓存普通表 。表名(key)用于筛选一组数据(这张表里的所有数据),记录的主键ID(field)作为每条数据(value)的唯一标识符。
二、使用Hash示例页面上经常有类似于下拉框的键值对。比如,颜色、性别。这些数据都会存放在系统的字典表中。
我考虑在系统上线的时候,把字典表的所有数据统统加载到Redis的缓存中。并且在每次操作字典表的时候,更新缓存。
比如有上面的这张字典表。假设有管理页面,加入一条记录,如果操作字典表成功,那么就查询这张字典表的所有数据,将其加入到Redis的缓存中。例如color作为type,能够标识出颜色大类。sex作为type,能够表示出性别大类。
数据结构示意图如下:
Key ----------------- field --------------------- value
自定义常量 type字段 对应种类的多条记录List
public Integer addParameter(Parameter parameter) {
parameter.setId(null);
mapper.insertSelective(parameter);
if (parameter.getId() > 0) {
//实时同步缓存
cacheAllConfig();
}
return parameter.getId();
}
private void cacheAllConfig() {
//清除上次缓存
redisTemplate.delete(Constant.MAP_KEY);
HashOperations<String, String, List> hashOperations = this.getHashOperations();
//获取字典表的所有数据
List parameters = mapper.getAll();
//字典表的type作为唯一标识符,标识一组数据
for (Parameter parameter : parameters) {
//对应API命令 Hget key field
List parametersList = hashOperations.get(Constant.MAP_KEY, parameter.getType());
if (parametersList == null || parametersList.isEmpty()) {
//如果添加的种类参数不在缓存中,那么就创建一个List
parametersList = new ArrayList();
}
parametersList.add(parameter);
hashOperations.put(Constant.MAP_KEY, parameter.getType(), parametersList);
}
}
private HashOperations getHashOperations() {
return redisTemplate.opsForHash();
}
如何获取呢?
public Map<String, List> getParameter() {
HashOperations<String, String, List> hashOperations = getHashOperations();
//Hash的entries命令,获取key对应的所有的 field - value
//这里的field就是 type, value就是type对应的多条记录
Map<String, List> result = hashOperations.entries(Constant.MAP_KEY);
return result;
}
public List getParameterByType(final String type) {
HashOperations<String, String, List> hashOperations = getHashOperations();
//基础的get命令 hget key filed
List result = hashOperations.get(Constant.MAP_KEY, type);
return result;
}
private HashOperations getHashOperations() {
return redisTemplate.opsForHash();
}
我先添加一个字典表数据,触发上面的加载缓存操作,把所有字典表数据根据type,加载进Redis缓存中。
再在页面上请求所有字典表数据,当然这些数据全部来自Redis中,就能避免与DB进行交互。
最后测试,根据type来获取指定的字典表数据。
作者:小大宇