redis注意点记录
1、stringRedisTemplate 它的key和Value的序列化方式默认就是String类型
2、stringRedisTemplate 操作Hash时:
2.1 添加数据 ,在实体转换为HashMap需要将对象字段的值转为String( 使用StringRedisTemplateredis
需要转换成的map的各个字段都是String类型),eg:
Map<String, Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(),
CopyOptions.create()
.setIgnoreNullValue(true)
.setFieldValueEditor((fieldName,fieldValue)->fieldValue.toString()));
stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY + token,userMap);
2.1.1 Hutool工具包的BeanUtil的beanToMap方法------空指针的问题 https://i.cnblogs.com/posts/edit;postId=17077647 修改为:
Map<String, Object> map = BeanUtil.beanToMap(dbShop,new HashMap<>(),
CopyOptions.create()
.setIgnoreNullValue(true)
.setFieldValueEditor((fieldName,fieldValue) -> {
if (fieldValue == null){
fieldValue = "0";
}else {
fieldValue = fieldValue.toString();
}
return fieldValue;
}));
stringRedisTemplate.opsForHash().putAll(CACHE_SHOP_KEY + id, map);
2.2 获取数据,
2.2.1使用entries获取hashMap 的所有键值对
Object shopMap = stringRedisTemplate.opsForHash().entries(CACHE_SHOP_KEY + id);
2.2.2使用get获取hashMap 的一个key 的键值对
Object str = stringRedisTemplate.opsForHash().get(CACHE_SHOP_KEY + id, "name");
3、stringRedisTemplate 操作string对应的实体对象时,需要转换成json,序列化与反序列化
//从redis查商铺信息缓存,存在缓存则直接返回,不存在则查数据库并写回到redis中
String redisShopJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);
//存在缓存
if (StrUtil.isNotBlank(redisShopJson)){
//字符串反序列化为实体对象
Shop shop = JSONUtil.toBean(redisShopJson, Shop.class);
return Result.ok(shop);
}
//存在缓存,查数据库
Shop dbShop = getById(id);
if(dbShop == null){
return Result.fail("商铺不存在!");
}
stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(dbShop));
return Result.ok(dbShop);
4、stringRedisTemplate 操作List的实体时,需要转换成json再存入redis https://blog.csdn.net/weixin_43658899/article/details/121040307
4.1 存入List类型到redis -- opsForList().range(key, start, end) 特殊用法:通过stringRedisTemplate.opsForList().range(key, 0, -1)可以查询索引第一个到索引倒数第一个(即所有数据)
https://blog.csdn.net/qq_52793248/article/details/128106178
List<String> shopTypeStr = stringRedisTemplate.opsForList().range(CACHE_TYPES_KEY, 0, -1);
if (CollectionUtil.isNotEmpty(shopTypeStr)){
List<ShopType> shopTypeList = new ArrayList<>();
for (int i = 0; i < shopTypeStr.size(); i++) {
ShopType shopType = JSONUtil.toBean(shopTypeStr.get(i), ShopType.class);
shopTypeList.add(shopType);
}
return Result.ok(shopTypeList);
}
4.2 redis中取出List类型 -- opsForList().rightPushAll 从右侧批量插入
List<ShopType> shopTypeList = query().orderByAsc("sort").list();
if (CollectionUtil.isNotEmpty(shopTypeList)){
List<String> shopTypeJson = new ArrayList<>();
for (int i = 0; i < shopTypeList.size(); i++) {
shopTypeJson.add(JSONUtil.toJsonStr(shopTypeList.get(i)));
}
//回写到redis
stringRedisTemplate.opsForList().rightPushAll(CACHE_TYPES_KEY, shopTypeJson);
return Result.ok(shopTypeList);
}
5、缓存更新策略
缓存与数据库的不论谁先后都有概率出现问题,由于操作redis的速度比操作数据库的要快,故在更新数据时选择先操作数据库,再删除缓存!
总结:
6、缓存穿透
//不存在缓存,查数据库
Shop dbShop = getById(id);
if(dbShop == null){
stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, "",CACHE_NULL_TTL, TimeUnit.MINUTES);
return Result.fail("商铺不存在!");
}
7、缓存雪崩
8、缓存击穿
逻辑过期:不给热点key设置TTl,而且在value中增加字段记录有效期时间,在代码中进行判断,如果过期,则开启新线程重建缓存,在重建完成之前,都返回旧的数据。
分类:
后端开发技术 / redis
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?