发表于: 2021-09-21 23:19:52
2 1052
一,今天完成的事情
任务六。
1,我设置了适合我的RedisConfig文件,配置合适的Bean。Redis涉及转换数据类型的问题,目前用的fastJson。Type能自动转换也设置好
ParserConfig.getGlobalInstance().addAccept("com.nicole.tileslogin.entity");
最终用的注解配置是:
package com.nicole.tileslogin.config;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* Created by daixiaoming on 2018-12-05.
*/
@Configuration
@PropertySource("classpath:redis.properties")
public class RedisConfig {
@Value("${hostName}")
private String hostName;
@Value("${port}")
private int port;
@Value("${pool.maxIdle}")
private int maxIdle;
@Value("${pool.minIdle}")
private int minIdle;
@Value("${pool.maxWaitMillis}")
private int maxWaitMillis;
@Value("${pool.maxTotal}")
private int maxTotal;
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(hostName);
redisStandaloneConfiguration.setPort(port);
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);
poolConfig.setMaxWaitMillis(maxWaitMillis);
poolConfig.setMaxTotal(maxTotal);
LettucePoolingClientConfiguration lettucePoolingClientConfiguration = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofSeconds(5000))
.shutdownTimeout(Duration.ZERO)
.poolConfig(poolConfig)
.build();
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, lettucePoolingClientConfiguration);
lettuceConnectionFactory.setShareNativeConnection(false);
return lettuceConnectionFactory;
}
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 设置键(key)的序列化采用StringRedisSerializer
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteClassName);
fastJsonRedisSerializer.setFastJsonConfig(fastJsonConfig);
// 全局开启AutoType,不建议使用
// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 建议使用这种方式,小范围指定白名单
// ParserConfig.getGlobalInstance().addAccept("com.doodl6.");
ParserConfig.getGlobalInstance().addAccept("com.nicole.tileslogin.entity");
// 设置值(value)的序列化采用FastJsonRedisSerializer
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
我的Redis测试用的是ValueOperations<String, List<ExcellentStudent>> valueOperations,限制类型。也可以用ListOperations,但是特地注意如果用这个,要考虑好类型转换的问题,比较会可能有类型转换问题。如果下面代码的list就是要转化的变量,要变成List<User>类型
objectMapper.convertValue(lists, new TypeReference<List<User>>() { });
我的test,存好后,取数据也成功。顺利把取出的数据封装成
List<ExcellentStudent>
2,测试,现在的方法可用,当然最好全部都是注入。
package com.nicole.tileslogin;
import com.nicole.tileslogin.config.RedisConfig;
import com.nicole.tileslogin.entity.ExcellentStudent;
import com.nicole.tileslogin.service.ExcellentStudentService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-mybatis.xml"})
public class RedisConfigTest {
@Autowired
private ExcellentStudentService excellentStudentService;
@Autowired
private RedisTemplate redisTemplate;
// private ListOperations<String, List<ExcellentStudent>> opsForList;
private ValueOperations<String, List<ExcellentStudent>> valueOperations;
@Before
public void setUp() throws Exception{
// opsForList = redisTemplate.opsForList();
valueOperations = redisTemplate.opsForValue();
}
@Test
@Transactional
@Rollback(true)
public void getExcStudentsTest(){
//只看前4个记录
int offset = 0;
int limit = 4;
String key = "studentList";
List<ExcellentStudent> studentList = new ArrayList<>();
boolean hasKey = redisTemplate.hasKey(key);
if(hasKey){
studentList = valueOperations.get(key);
int size = studentList.size();
for (int i = 0; i < size; i++) {
System.out.println("从缓存中获取数据:"+ studentList.get(i).getName());
}
System.out.println("-----------------------------");
}else{
studentList =
excellentStudentService.queryAllByLimit( offset, limit);
System.out.println("查询数据库获取数据:"+studentList.get(0).getName());
valueOperations.set("studentList", studentList);
System.out.println("------------写入缓存---------------------");
}
}
}
存储好后成功取的结果,成功,我选择直接打印出来
3,将Redis缓存加入service层
@Service("excellentStudentService")
public class ExcellentStudentServiceImpl implements ExcellentStudentService {
@Autowired
private ExcellentStudentDao excellentStudentDao;
@Autowired
private RedisTemplate redisTemplate;
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
@Override
public ExcellentStudent queryById(Long id) {
return this.excellentStudentDao.queryById(id);
}
/**
* 查询多条数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
@Override
public List<ExcellentStudent> queryAllByLimit(int offset, int limit) {
String key = "studentList";
ValueOperations<String, List<ExcellentStudent>> valueOperations = redisTemplate.opsForValue();
List<ExcellentStudent> studentList = new ArrayList<>();
boolean hasKey = redisTemplate.hasKey(key);
if(hasKey){
studentList = valueOperations.get(key);
}else{
studentList =
excellentStudentDao.queryAllByLimit( offset, limit);
if(studentList.size() < 1) {
valueOperations.set("studentList", null);
}
valueOperations.set("studentList", studentList);
}
return studentList;
}
运行这个
queryAllByLimit
方法有关的controller层,成功访问,而且在缓存那个打印到控制台过,是在Redis缓存访问。
还是成功访问网页。
4,但是,在本地用JMeter压力测试,发现本来不会出现错误的100并发,用Redis出现了错误。我的图片在数据库中存的是路径,所以通过Redis就算是图片路径拿图片。
对我的本地Windows压力也过大。
5,JMeter测试在云Linux上的http://47.111.153.120/tiles_login/excellentStudent/salaryDesc
100没有错误
500远程压力比较明显
6,5的远程Linux吞吐量不行。先不测其它了。先测一测Json的返回格式在本地,是不是吞吐量赶紧能上去。
@RequestMapping(value = "/salaryDescJson", method = RequestMethod.GET)
@ResponseBody
public Map<String, Object> excellentStudentJson(){
int offset = 0;
int limit = 4;
List<ExcellentStudent> studentList = excellentStudentService.queryAllByLimit( offset, limit);
if (null == studentList) {
return Restful.set(400, "查找优秀学员失败" );
} else {
return Restful.set(200, "查找优秀学员成功", studentList);
}
}
有缓存本地100表现都很差
注释,不用缓存,还是原来的
return excellentStudentDao.queryAllByLimit(offset,limit);
测试返回JSON的带
@ResponseBody
没有我的Redis代码,本地反而跑得正常了
本地不用Redis 500也正常
1000有limit的有问题正常
二,今天问题
数据类型转换要小心,要花心思。就算用fastJson等工具,要做明白不算简单。
网站吞吐很差。
三,今天的收获
Redis拦在MySQL前面。类型使用,泛型实战。
xml配置和注解文件用注解配置转换。
四,明天的计划
任务6
在Linux上安装Redis,并测试war包。比较有和没有Redis的表现情况。
换没有offset,limit的相对简单的语句测试。redis是有用的。
评论