常见的的序列化反序列方式的效率:

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的方法的更多相关文章

  1. 分布式锁的三种实现方式 数据库、redis、zookeeper

    版权声明: https://blog.csdn.net/wuzhiwei549/article/details/80692278 一.为什么要使用分布式锁 我们在开发应用的时候,如果需要对某一个共享变 ...

  2. 并发编程系列小结(线程安全,synchronized,脏读,线程间的通信wait/notify,线程的三种实现方式Demo,可替代wait/notify的方法)

    线程安全: 当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法就是线程安全的) synchronized: 可以在任意对象或方法上加锁,而加锁的这段代码称为 ...

  3. 大数据学习day13------第三阶段----scala01-----函数式编程。scala以及IDEA的安装,变量的定义,条件表达式,for循环(守卫模式,推导式,可变参数以及三种遍历方式),方法定义,数组以及集合(可变和非可变),数组中常用的方法

    具体见第三阶段scala-day01中的文档(scala编程基础---基础语法)  1. 函数式编程(https://www.cnblogs.com/wchukai/p/5651185.html): ...

  4. python笔记-20 django进阶 (model与form、modelform对比,三种ajax方式的对比,随机验证码,kindeditor)

    一.model深入 1.model的功能 1.1 创建数据库表 1.2 操作数据库表 1.3 数据库的增删改查操作 2.创建数据库表的单表操作 2.1 定义表对象 class xxx(models.M ...

  5. 2019年6月14日 Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)

    摘要 MTV与MVC 多对多表三种创建方式 ajax ,前后端传输数据编码格式contentType 批量插入数据和自定义分页器 一.MVC与MTV MVC(Model View Controller ...

  6. Storm 学习之路(六)—— Storm项目三种打包方式对比分析

    一.简介 在将Storm Topology提交到服务器集群运行时,需要先将项目进行打包.本文主要对比分析各种打包方式,并将打包过程中需要注意的事项进行说明.主要打包方式有以下三种: 第一种:不加任何插 ...

  7. Storm 系列(六)—— Storm 项目三种打包方式对比分析

    一.简介 在将 Storm Topology 提交到服务器集群运行时,需要先将项目进行打包.本文主要对比分析各种打包方式,并将打包过程中需要注意的事项进行说明.主要打包方式有以下三种: 第一种:不加任 ...

  8. Django-多对多关系的三种创建方式-forms组件使用-cookie与session-08

    目录 表模型类多对多关系的三种创建方式 django forms 组件 登录功能手写推理过程 整段代码可以放过来 forms 组件使用 forms 后端定义规则并校验结果 forms 前端渲染标签组件 ...

  9. 三种存储方式DAS、NAS、SAN

    ------------恢复内容开始------------ 一.DAS.NAS.SAN在存储领域的位置 随着主机.磁盘.网络等技术的发展,数据存储的方式和架构也在一直不停改变,本文主要介绍目前主流的 ...

随机推荐

  1. click点击事件先后顺序的问题

    //页面加载时,每秒钟调用一次var times = setInterval("loadFlws()","1000"); function loadFlws() ...

  2. 帝都Day4(3)——还是数据结构

    可并堆 左偏树中 dist[x]=dist[rs[x]]+1 合并的时候,把权志较大的根作为根节点,把这棵树右子树和另一棵树合并. 说明白点:(上图描述有点问题) 设x表示根权值较大的左偏树,y表示根 ...

  3. wampserver切换php版本问题

    安装的wampserver有两个php版本,一个5.6的.一个7.1的,之前一直使用的php5.6的版本,今天切换7.1版本,切换成功了 phpinfo显示的版本也是7.1,但是php -v显示的却始 ...

  4. 关于双端队列 deque 模板 && 滑动窗口 (自出)

    嗯... deque 即为双端队列,是c++语言中STL库中提供的一个东西,其功能比队列更强大,可以从队列的头与尾进行操作... 但是它的操作与队列十分相似,详见代码1: 1 #include < ...

  5. An internal error occurred during: "Add Deployment". Container with path org.eclipse.jdt.launching.

    导入非本机项目出现这种错误,原因就是JDK版本不一致. 具体解决步骤如下: 右键项目名→Properties→JavaBuild Path→Libraries→选中JRE SystemLibrary[ ...

  6. Ubuntu系统下同时打开多个终端窗口的软件

    sudo apt-get install Terminator

  7. scau 8616 汽车拉力比赛

          上次我们过了二分图的最佳匹配,现在我们看一道题目,经典的二分图的最佳匹配题目 8616 汽车拉力比赛 时间限制:500MS  内存限制:1000K提交次数:71 通过次数:24 题型: 编 ...

  8. aop 切面配置

    <bean id="userServiceImpl" class="com.bj.aop.xml.before.UserServiceImpl">& ...

  9. Kotlin基础知识

    1. 改进点/基础 //安全判空 val length = text?.length; //类型转换 if (object is Car) { var car = object as Ca } //操 ...

  10. cucumber的疑问解答

    在cucumber的自动化测试框架下面,在一个steps文件中定义的@page对象,可以在其他的不同的steps文件中调用,在整个的场景生命周期中都是有效的 原因:cucumber开始执行时,一次性把 ...