在项目中使用redis作为缓存,将对象转换为json字符串存储到了redis,然后将字符串获取处来再转换成对象,感觉会有性能上的损耗,
于是突发奇想使用的kryo将对象转成字节数组存入到redis中,然后将redis存储的字节数组取出来再反序列化成对象。
具体代码如下
1.maven引入依赖
<dependency> <groupId>com.esotericsoftware</groupId> <artifactId>kryo</artifactId> <version>5.0.3</version> </dependency>
2.因在并发的过程中遇到kryo报错,后来查找原因存在线程不安全问题于是做了以下配置,使用ThreadLocal来获取Kryo对象
@Configuration public class KryoConfig { @Bean public ThreadLocal<Kryo> kryoPool() { ThreadLocal<Kryo> pool = new ThreadLocal<Kryo>() { @Override protected Kryo initialValue() { Kryo kryo = new Kryo(); kryo.register(UserVaccineAppointCacheEntity.class); kryo.register(UserVaccineAppoint.class); kryo.register(Date.class); kryo.register(Duration.class); kryo.register(Instant.class); kryo.register(LocalDate.class); kryo.register(LocalTime.class); kryo.register(LocalDateTime.class); kryo.register(ZoneOffset.class); kryo.register(ZoneId.of("UTC+08:00").getClass()); // ZoneRegion kryo.register(ZoneId.class); kryo.register(OffsetTime.class); kryo.register(OffsetDateTime.class); kryo.register(ZonedDateTime.class); kryo.register(Year.class); kryo.register(YearMonth.class); kryo.register(MonthDay.class); kryo.register(Period.class); return kryo; } }; return pool; } }
3.使用的业务简化代码使用redisTemplate.execute执行redis命令
@Resource private ThreadLocal<Kryo> kryoPool;
public StudentEntity getById(String idKey) { Object data = redisTemplate.execute(connection -> { byte[] bytes = connection.get(idKey.getBytes()); return bytes; }, true); if(data!=null) { byte[] res = (byte[])data; ByteArrayInputStream bis = new ByteArrayInputStream(res); Input input = new Input(bis); Kryo kryo = kryoPool.get(); StudentEntity cacheEntity = kryo.readObject(input, StudentEntity.class); return cacheEntity; } return null; }
public void insertCache(StudentEntity cacheEntity) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); Output output = new Output(bos, 100000); Kryo kryo = kryoPool.get(); kryo.writeObject(output, userVaccineAppoint); byte[] valueBytes = output.getBuffer(); byte[] keyBytes = cacheEntity.getIdKey().getBytes(); kryo.reset(); redisTemplate.execute(connection->{ connection.set(keyBytes, valueBytes); return null; },true); }
使用redis来缓存kryo序列化对象时需要注意字段的增减会存在报错情况