redis全称:REmote DIctionary Server,是可支持网络、可基于内存亦可持久化的日志型、Key-Value高性能数据库,并提供多种语言的API,它通常被称为数据结构服务器。
- Redis hash是一个键值对集合,一个键对应多个值对[field,value]
- 也就是key-field+value形式,可以理解成java的map< string,map<string,string>> ,三个string依次对应key、field、value。
Redis hash是一个string类型的field和value的映射表,适合于存储对象
例如,在key名为SERIAL_TASK的情况下:
先配置redis的配置类
package com.cascade.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.net.UnknownHostException; @Configuration public class RedisConfiguration { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<String, Object> template = new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); // Json 配置序列化 // 使用 jackson 解析任意的对象 Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); // 使用 objectMapper 进行转义 ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); // String 的序列化 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // key 采用 String 的序列化方式 template.setKeySerializer(stringRedisSerializer); // Hash 的 key 采用 String 的序列化方式 template.setHashKeySerializer(stringRedisSerializer); // value 采用 jackson 的序列化方式 template.setValueSerializer(stringRedisSerializer); // Hash 的 value 采用 jackson 的序列化方式 template.setHashValueSerializer(stringRedisSerializer); // 把所有的配置 set 进 template template.afterPropertiesSet(); return template; } @Bean public HashOperations<String, String, String> hashOperations(RedisTemplate<String, String> redisTemplate) { return redisTemplate.opsForHash(); } @Bean public RedisSerializer<String> redisSerializer(RedisTemplate<String, String> redisTemplate) { return redisTemplate.getStringSerializer(); } }
使用 Redis 有哪些好处?
-
速度快,因为数据存在内存中,类似于 HashMap ,HashMap 的优势就是查找和操作的时间复杂度是O(1)
-
支持丰富的数据类型,支持:String、list、set、sortedset、hash
-
支持事务,操作的原子性,所谓的原子性就是对数据的更改要么全部执行,要么不执行
-
丰富的特性,可用于缓存,消息,按 key 设置过期时间,过期后会自动删除
java代码引用
@Service
@Slf4j
public class RedisCacheFetchStrategy implements CacheFetchStrategy {
@Resource
private RedisTemplate<String, String> redisTemplate;
@Resource
private RedisSerializer<String> redisSerializer;
@Resource
private HashOperations<String, String, String> hashOperations;
/**
* 分割
*/
String PARTING = "@";
/**
*
* @param hashkey
* @param sysUser
* @param hashName
*/
@Override
public void fetchSysUser(String hashkey, SysUser sysUser, String hashName) {
Map<byte[], byte[]> map = new HashMap<>();
String hashValue = String.valueOf(sysUser.getId()).concat(PARTING).concat(sysUser.getName())
.concat(PARTING).concat(StringUtils.isEmpty(sysUser.getProvince()) ? "":sysUser.getProvince());
map.put(redisSerializer.serialize(hashkey), redisSerializer.serialize(hashValue));
log.info("开始缓存添加,hashName=>{}, hashkey=>{}, hashvalue=>{}", hashName, hashkey, hashValue);
this.redisTemplate.executePipelined((RedisCallback<Void>) redisConnection -> {
RedisHashCommands redisHashCommands = redisConnection.hashCommands();
//redis所在的key
byte[] serialize = redisSerializer.serialize(hashName);
if (serialize != null) {
redisHashCommands.hMSet(serialize, map);
}
return null;
});
log.info("开始设置过期时间,时间{},单位{}=>",24,TimeUnit.HOURS);
this.redisTemplate.expire(hashName,24, TimeUnit.HOURS);
log.info("获取hashkey 中fieId数据");
String message = hashOperations.get(InsideStationMessage.FILE_AUDIT_TASK, hashkey);
log.info("删除某个hashkey");
hashOperations.delete(InsideStationMessage.FILE_AUDIT_TASK, hashkey);
log.info("直接销毁hash");
this.redisTemplate.unlink(hashName);
}
使用hash 省内存。
在hash类型中,一个key可以对应多个多个field,一个field对应一个value。
将一个对象存储为hash类型的好处:
-
较于每个字段都单独存储成string类型来说,更能节约内存;
-
将具有同一类规则的数据放到redis中的一个数据容器里,防止数据上不同规则的key值上的相斥,便于查找数据。