三种序列化方式存取redis的方法
常见的的序列化反序列方式的效率:
protoBuf(PB) > fastjson > jackson > hessian > xstream > java
数据来自于:https://github.com/eishay/jvm-serializers/wiki
所以我选择了java方式、jackson方式、fastjson方式、pb方式做了封装并测试,测试结果如下:
jackson、pb、fastjson差不太多,jackson稍好些,java方式非常慢不推荐,jackson是springboot自带的json序列化工具,所以推荐这种方式做redis对象存取。
下面是四种实现方式:
java自带序列化
序列化工具方法
/**
* 序列化
*
* @param object
* @return
*/
public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
} /**
* 反序列化
*
* @param bytes
* @return
*/
public static Object unserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
redisUtils
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 以二进制序列化方式向redis保存对象 2019
*
* @param key
* @param value
*/
public void setObj(String key, Object value) {
final byte[] vbytes = SerializeUtil.serialize(value);
redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
// connection.set(redisTemplateSer.getStringSerializer().serialize(key), vbytes);
connection.set(SerializeUtil.serialize(key), vbytes);
return null;
}
});
} /**
* 以二进制序列化方式从redis获取对象 2019
*
* @param key
* @param <T>
* @return
*/
public <T> T getObj(String key) {
return redisTemplate.execute(new RedisCallback<T>() {
@Override
public T doInRedis(RedisConnection connection) throws DataAccessException {
// byte[] keyByte = redisTemplateSer.getStringSerializer().serialize(key);
byte[] keyByte = SerializeUtil.serialize(key); if (connection.exists(keyByte)) {
byte[] valuebytes = connection.get(keyByte);
@SuppressWarnings("unchecked")
T value = (T) SerializeUtil.unserialize(valuebytes);
return value;
}
return null;
}
});
}
Jackson、fastjson
序列化工具方法
/**
* jackson序列化反序列化工具
*/
private static ObjectMapper objectMapper = new ObjectMapper(); public static <T> String obj2String(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
} catch (Exception e) {
e.printStackTrace();
return null;
}
} //字符串转对象
public static <T> T string2Obj(String str, Class<T> clazz) {
if (StringUtils.isEmpty(str) || clazz == null) {
return null;
}
try {
return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz);
} catch (IOException e) {
e.printStackTrace();
return null;
}
} // /**
// * fastjson序列化反序列化工具
// */
// public static <T> String obj2String(T obj) {
// return JSON.toJSONString(obj);
// }
//
// //字符串转对象
// public static <T> T string2Obj(String str, Class<T> clazz) {
// return JSON.parseObject(str,clazz);
// }
redisUtils
/**
* 以JSON序列化方式向redis保存对象 推荐这种用法速度快 2019
* @param key
* @param value
*/
public void setObjJson(String key,Object value){
redisTemplate.opsForValue().set(key,SerializeUtil.obj2String(value));
} /**
* 以JSON序列化方式从redis获取对象 推荐这种用法速度快 2019
* @param key
* @param clazz
* @param <T>
* @return
*/
public <T> T getObjJson(String key,Class<T> clazz){
String strValue = redisTemplate.opsForValue().get(key);
if(!StringUtils.isEmpty(strValue)){
T value = SerializeUtil.string2Obj(strValue,clazz);
return value;
}
return null;
}
ProtoBuf方式
maven依赖
<!-- protostuff -->
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.4.0</version>
</dependency>
序列化工具方法
/**
* protobuf序列化工具
*/
public static <T> byte[] serializePb(T o) {
Schema schema = RuntimeSchema.getSchema(o.getClass());
return ProtobufIOUtil.toByteArray(o, schema, LinkedBuffer.allocate(256));
} public static <T> T unserializePb(byte[] bytes, Class<T> clazz) { T obj = null;
try {
obj = clazz.newInstance();
Schema schema = RuntimeSchema.getSchema(obj.getClass());
ProtostuffIOUtil.mergeFrom(bytes, obj, schema);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} return obj;
}
redisUtils,pb方式如果是嵌套对象会有一定问题(这块回头再研究一下),并且需要序列化的成员变量需要添加@Tag(7)注解,如:
@Data
public class SimplePojo {
@Tag(1)
private String a;
@Tag(2)
private String b;
@Tag(3)
private String c;
/**
* 以pb序列化方式向redis保存对象 2019
*
* @param key
* @param value
*/
public void setObjPb(String key, Object value) {
final byte[] vbytes = SerializeUtil.serializePb(value);
redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
connection.set(SerializeUtil.serializePb(key), vbytes);
return null;
}
});
} /**
* 以pb序列化方式从redis获取对象 2019
*
* @param key
* @param <T>
* @return
*/
public <T> T getObjPb(String key,Class<T> clazz) {
return redisTemplate.execute(new RedisCallback<T>() {
@Override
public T doInRedis(RedisConnection connection) throws DataAccessException {
byte[] keyByte = SerializeUtil.serializePb(key); if (connection.exists(keyByte)) {
byte[] valuebytes = connection.get(keyByte);
@SuppressWarnings("unchecked")
T value = (T) SerializeUtil.unserializePb(valuebytes,clazz);
return value;
}
return null;
}
});
}
Fork From GIT
更详细的的源码详见:https://gitee.com/zxporz/redistest/blob/master/src/main/java/org/zxp/redis/utils/RedisUtil.java
欢迎fork
三种序列化方式存取redis的方法的更多相关文章
- 分布式锁的三种实现方式 数据库、redis、zookeeper
版权声明: https://blog.csdn.net/wuzhiwei549/article/details/80692278 一.为什么要使用分布式锁 我们在开发应用的时候,如果需要对某一个共享变 ...
- 并发编程系列小结(线程安全,synchronized,脏读,线程间的通信wait/notify,线程的三种实现方式Demo,可替代wait/notify的方法)
线程安全: 当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法就是线程安全的) synchronized: 可以在任意对象或方法上加锁,而加锁的这段代码称为 ...
- 大数据学习day13------第三阶段----scala01-----函数式编程。scala以及IDEA的安装,变量的定义,条件表达式,for循环(守卫模式,推导式,可变参数以及三种遍历方式),方法定义,数组以及集合(可变和非可变),数组中常用的方法
具体见第三阶段scala-day01中的文档(scala编程基础---基础语法) 1. 函数式编程(https://www.cnblogs.com/wchukai/p/5651185.html): ...
- python笔记-20 django进阶 (model与form、modelform对比,三种ajax方式的对比,随机验证码,kindeditor)
一.model深入 1.model的功能 1.1 创建数据库表 1.2 操作数据库表 1.3 数据库的增删改查操作 2.创建数据库表的单表操作 2.1 定义表对象 class xxx(models.M ...
- 2019年6月14日 Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)
摘要 MTV与MVC 多对多表三种创建方式 ajax ,前后端传输数据编码格式contentType 批量插入数据和自定义分页器 一.MVC与MTV MVC(Model View Controller ...
- Storm 学习之路(六)—— Storm项目三种打包方式对比分析
一.简介 在将Storm Topology提交到服务器集群运行时,需要先将项目进行打包.本文主要对比分析各种打包方式,并将打包过程中需要注意的事项进行说明.主要打包方式有以下三种: 第一种:不加任何插 ...
- Storm 系列(六)—— Storm 项目三种打包方式对比分析
一.简介 在将 Storm Topology 提交到服务器集群运行时,需要先将项目进行打包.本文主要对比分析各种打包方式,并将打包过程中需要注意的事项进行说明.主要打包方式有以下三种: 第一种:不加任 ...
- Django-多对多关系的三种创建方式-forms组件使用-cookie与session-08
目录 表模型类多对多关系的三种创建方式 django forms 组件 登录功能手写推理过程 整段代码可以放过来 forms 组件使用 forms 后端定义规则并校验结果 forms 前端渲染标签组件 ...
- 三种存储方式DAS、NAS、SAN
------------恢复内容开始------------ 一.DAS.NAS.SAN在存储领域的位置 随着主机.磁盘.网络等技术的发展,数据存储的方式和架构也在一直不停改变,本文主要介绍目前主流的 ...
随机推荐
- click点击事件先后顺序的问题
//页面加载时,每秒钟调用一次var times = setInterval("loadFlws()","1000"); function loadFlws() ...
- 帝都Day4(3)——还是数据结构
可并堆 左偏树中 dist[x]=dist[rs[x]]+1 合并的时候,把权志较大的根作为根节点,把这棵树右子树和另一棵树合并. 说明白点:(上图描述有点问题) 设x表示根权值较大的左偏树,y表示根 ...
- wampserver切换php版本问题
安装的wampserver有两个php版本,一个5.6的.一个7.1的,之前一直使用的php5.6的版本,今天切换7.1版本,切换成功了 phpinfo显示的版本也是7.1,但是php -v显示的却始 ...
- 关于双端队列 deque 模板 && 滑动窗口 (自出)
嗯... deque 即为双端队列,是c++语言中STL库中提供的一个东西,其功能比队列更强大,可以从队列的头与尾进行操作... 但是它的操作与队列十分相似,详见代码1: 1 #include < ...
- An internal error occurred during: "Add Deployment". Container with path org.eclipse.jdt.launching.
导入非本机项目出现这种错误,原因就是JDK版本不一致. 具体解决步骤如下: 右键项目名→Properties→JavaBuild Path→Libraries→选中JRE SystemLibrary[ ...
- Ubuntu系统下同时打开多个终端窗口的软件
sudo apt-get install Terminator
- scau 8616 汽车拉力比赛
上次我们过了二分图的最佳匹配,现在我们看一道题目,经典的二分图的最佳匹配题目 8616 汽车拉力比赛 时间限制:500MS 内存限制:1000K提交次数:71 通过次数:24 题型: 编 ...
- aop 切面配置
<bean id="userServiceImpl" class="com.bj.aop.xml.before.UserServiceImpl">& ...
- Kotlin基础知识
1. 改进点/基础 //安全判空 val length = text?.length; //类型转换 if (object is Car) { var car = object as Ca } //操 ...
- cucumber的疑问解答
在cucumber的自动化测试框架下面,在一个steps文件中定义的@page对象,可以在其他的不同的steps文件中调用,在整个的场景生命周期中都是有效的 原因:cucumber开始执行时,一次性把 ...