您的位置 首页 > 数码极客

〈redis如何存储list〉Redis存储hash!

一、概述

最近在做性能优化,之前有一个业务是这样实现的:

1.温度报警后第三方通讯管理机直接把报警信息保存到数据库

2.我们在数据库中添加触发器,(BEFORE INSERT)根据这条报警信息处理业务逻辑,在数据库中插入“其他业务数据”

3.前端setTimeout每隔5秒ajax去后端查询“其他业务数据”(查库)

优化后这样实现:

两个微服务,消息中间件专门一个服务,接收消息存入数据库,存入redis;业务服务直接从redis获取

1.MQTT订阅通讯管理机报警事件主题

2.发生报警后,java中根据报警信息保存“其他业务数据”到数据库并放入redis缓存

3.前端setTimeout每隔5秒ajax去后端查询“其他业务数据”(改为从redis中获取)

4.下一步计划使用WebSocekt,去掉前端setTimeout

二、SpringBoot配置redis

、a、@EnableCaching等等这些配置就不列出来了,大家可以百度,提一下RedisTemplate的配置

RedisTemplate<String, Object>可以直接存直接存List、Map等,使用jackson2jsonRedisSerializer序列化,

package ;

import java.lang.re;

import org.;

import org.;

import org.;

import org.;

import org.;

import org.;

import org.;

import org.;

import org.;

import org.;

import org.;

import com.;

import com.;

import com.;

import com.;

import com.;

@Configuration

public class RedisConfiguration {

@Bean("jsonRedisCache")

public CacheManager cacheManager(@Autowired RedisTemplate<String, Object> redisTemplate) {

return new RedisCacheManager(redisTemplate);

}

@Bean

public KeyGenerator keyGenerator() {

return new KeyGenerator() {

@Override

public Object generate(Object target, Method method, Object... params) {

StringBuilder sb = new StringBuilder();

().getName());

());

for (Object obj : params) {

());

}

return ();

}

};

}

@Bean

public RedisTemplate<String, Object> redisTemplate(@Autowired RedisConnectionFactory cf) {

RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();

redi(new StringRedisSerializer());

redi(jackson2JsonRedisSerializer());

redi(jackson2JsonRedisSerializer());

redi(cf);

redi();

return redisTemplate;

}

@SuppressWarnings({ "unchecked", "rawtypes" })

@Bean

public Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {

final Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(

Object.class);

final ObjectMapper objectMapper = Jack().build();

objec);

objec);

objec);

objec, J);

objec);

jack(objectMapper);

return jackson2JsonRedisSerializer;

}

}

三、List对象存入redis遇到的问题

1.@Cacheable不起作用问题

刚开始,计划在service层方法上使用注解@Cacheable进行缓存,但是redis没有保存,最后百度得到答案:一个类中@Cacheable标注的方法不能被本类中其他方法调用,否则缓存不起作用

修改类方法调用后此问题解决

错误的方法调用:

正确的调用:其他类调用该方法

这其中有个报错:No cache could be resolved for 'Builder[public java.u com.es.)] caches=[] | key=''EvrAlarm-'+#accountId' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'' using resolver 'org.;. At least one cache should be provided per cache operation.

@Cacheable注解中添加cacheNames即可

package ;

import java.u;

import java.u;

import java.u;

import org.;

import org.;

import org.;

import com.es.en;

import com.es.re;

@Service

public class EvrAlarmCacheService {

@Autowired

private EvrAlarmDao evrAlarmDao;

@Cacheable(cacheNames="EvrAlarms",key="'EvrAlarm-'+#accountId")

public List<EvrAlarm> getEvrAlarmByAccountId(String accountId){

Map<String,Object> params = new HashMap<>();

("accountId", accountId);

("limit", 1);

List<EvrAlarm> evrAlarms = evrAlarmDao.selectEvrAlarmByAccount(params);

return evrAlarms;

}

}

redis中存储的数据如下图:

2.Could not resolve type id 'com.es.xx.evralarm.EvrAlarm' into a subtype of [simple type, class java.lang.Object]: no such class found

at [Source: [B@29a6e242; line: 1, column: 60] (through reference chain: java.u[0])

业务服务中原代码:

@Cacheable(cacheNames="EvrAlarms",key="'EvrAlarm-'+#accountId")

public List<EvrAlarm> selectEvrAlarmByAccount(String accountId){

Map<String,Object> params = new HashMap<>();

("accountId", accountId);

return evrAlarmDao.selectEvrAlarmByAccount(params);

}

看到一遍文档后明白了,根本原因是:两个微服务,实体类内容虽然一样,但是类路径不一样

四、使用StringRedisTemplate、RedisTemplate<String, Object>

进一步分析发现使用@Cacheable有问题,消息中间件收到第二条报警消息,如果业务系统没有处理第一条报警消息(redis中未删除,同样的key redis中已有一条)则redis中的信息不会更新

应该是:消息中间件每次接收消息,处理后都往redis中更新

使用RedisTemplate<String, Object>直接保存List对象,redis存储中会携带一个类路径信息("com.es.xx.evralarm.EvrAlarm"),业务服务获取的时候无法解析(两个实体类内容相同,类路径不同),只能使用StringRedisTemplate了,只能是在redis存取前后自己手动对象转json

使用Gson直接把要保存的List<>对象转成json再保存到redis

中间件所在服务存入redis:

package com.xx.;

import java.u;

import java.u;

import java.u;

import org.;

import org.;

import org.;

import org.;

import com.es.en;

import com.es.re;

import com.google.g;

@Service

public class EvrAlarmCacheService {

@Autowired

private EvrAlarmDao evrAlarmDao;

@Autowired

private StringRedisTemplate redisTemplate;

public List<EvrAlarm> getEvrAlarmByAccountId(String accountId){

Map<String,Object> params = new HashMap<>();

("accountId", accountId);

("limit", 1);

List<EvrAlarm> evrAlarms = evrAlarmDao.selectEvrAlarmByAccount(params);

//redis缓存

ValueOperations<String,String> vo = redi();

Gson gson = new Gson();

vo.set("EvrAlarm-"+accountId, g(evrAlarms));

return evrAlarms;

}

}

业务服务从redis中取:

从redis中获取key对应的value,得到string类型的value,使用Gson转成List<>对象

1

<strong><span style="color: #ff0000"><span style="color: #000000">查询:</span></span></strong>

/**

* 根据账户ID查询最新告警信息

* */

public List<EvrAlarm> selectEvrAlarmByAccount(String accountId){

//redis缓存中获取

ValueOperations<String,String> vo = redi();

String value = vo.get("EvrAlarm-"+accountId);

Gson gson = new Gson();

List<EvrAlarm> evrAlarms = g(value, Li);

return evrAlarms == null ? new ArrayList<>() : evrAlarms;

}<br><br>

业务操作删除、同时删除redis:

public void deleteAccountEvralarm(String accountId, String evrAlarmId){

Map<String, Object> queryMap = new HashMap<>();

queryMap.put("accountId", accountId);

queryMap.put("evrAlarmId", evrAlarmId);

accoun(queryMap);

//redis删除缓存

redi("EvrAlarm-"+accountId);

}

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“redis如何存储list,Redis存储hash,redis如何存储list对象,Redis如何存储数据,Redis如何存储热点数据,Redis如何存储百万数”边界阅读