Redis 可以通过客户端命令redis-cli 直接连接, 然后直接操作其中的数据。当使用redis 存储一些敏感数据,或者是数据较大的数据时,我们可以对value进行加密序列化或压缩序列化。对于节省内存而言,采用Gzip压缩也是一个不错的方案。 笔者采用的方案是,先将对象序列化json, 然后再对json进行Gzip 压缩.
1. 自定义压缩序列化
1.1 GzipJsonSerializer
- 笔者json序列化采用默认的jackson 序列化方式, 所以笔者直接继承GenericJackson2JsonRedisSerializer 即可, 或者实现RedisSerializer 接口
- 序列化: 先进行jso序列化, 再进行压缩
- 反序列化: 先进行解压缩, 再进行反序列化
public class GzipJsonSerializer extends GenericJackson2JsonRedisSerializer {
@Override
public byte[] serialize(Object source) throws SerializationException {
// 先序列化java对象为json字节数组
byte[] bytes = super.serialize(source);
// 再将json 字节数组进行gzip压缩
return GzipUtils.compress(bytes);
}
@Override
public Object deserialize(byte[] source) throws SerializationException {
// 先解压字节数组为json字节数组
byte[] bytes = GzipUtils.unCompress(source);
// 在序列化json字节数组为java 对象
return super.deserialize(bytes);
}
}
1.2 java Gzip工具类
自定义一个gzip 压缩解压缩工具类, 实现对字节数组的压缩与解压缩.
public class GzipUtils {
/**
* @param bytes 字节数组
* @return byte[]
* @description 压缩字节数组
*/
public static byte[] compress(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
//将byte数据读入文件流
ByteArrayOutputStream bos = null;
GZIPOutputStream gzipos = null;
try {
bos = new ByteArrayOutputStream();
gzipos = new GZIPOutputStream(bos);
gzipos.write(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
closeStream(gzipos);
closeStream(bos);
}
return bos.toByteArray();
}
/**
* @param bytes Gzip压缩的字节数组
* @return byte[]
* @description 解压缩字节数组
*/
public static byte[] unCompress(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
ByteArrayOutputStream byteAos = null;
ByteArrayInputStream byteArrayIn = null;
GZIPInputStream gzipIn = null;
try {
byteArrayIn = new ByteArrayInputStream(bytes);
gzipIn = new GZIPInputStream(byteArrayIn);
byteAos = new ByteArrayOutputStream();
byte[] b = new byte[4096];
int temp = -1;
while ((temp = gzipIn.read(b)) > 0) {
byteAos.write(b, 0, temp);
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
closeStream(byteAos);
closeStream(gzipIn);
closeStream(byteArrayIn);
}
return byteAos.toByteArray();
}
/**
* 关闭流
*
* @param oStream
*/
private static void closeStream(Closeable oStream) {
if (null != oStream) {
try {
oStream.close();
} catch (IOException e) {
oStream = null;//赋值为null,等待垃圾回收
e.printStackTrace();
}
}
}
}
1.3 配置自定义RedisTemplate
@Bean("gzipJsonRedisTemplate")
public RedisTemplate<Object, Object> gzipJsonRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object,Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GzipJsonSerializer());
return template;
}
2. 测试
2.1 测试用例
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestGzipJsonTemplate {
@Autowired
private RedisTemplate gzipJsonRedisTemplate;
@Test
public void test(){
UserPO userPO = new UserPO("zhangsan", "123456", 20);
ValueOperations ops = this.gzipJsonRedisTemplate.opsForValue();
ops.set("zhangsan", userPO);
System.out.println(ops.get("zhangsan"));
}
}
2.2 redis 中存储
使用redis-cli 命令查看redis 中的存储形式
127.0.0.1:6379> get zhangsan
"\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00\xabVrH\xceI,.V\xb2R\xca/J\xd7\xab\xca\xcfKO\xd3\xcbIM,\xca\xd3+N)\xd2\xcb10\xd4\x0b-N-\n\xf0W\xd2Q*\x052\xf2\x12sS\x81j\xab2\x12\xf3\xd2\x8b\x13\xf3\x80\xa2\x05@\xdd\xe5\xf9E)@QC#c\x13S3\xa0Xb:P\x91\x91A-\x00\xad\xc9v~^\x00\x00\x00"