高性能的序列化与反序列化:kryo的简单使用
前言:kryo是个高效的java序列化/反序列化库,目前Twitter、yahoo、Apache、strom等等在使用该技术,比如Apache的spark、hive等大数据领域用的较多。
为什么使用kryo而不是其他?
因为性能足够好。比kyro更高效的序列化库就只有google的protobuf了(而且两者性能很接近),protobuf有个缺点就是要传输的每一个类的结构都要生成对应的proto文件(也可以都放在同一个proto文件中,如果考虑到扩展性的话,不建议放在一个proto文件中),如果某个类发生修改,还得重新生成该类对应的proto文件;另外考虑到项目中用的全部是java技术栈,不存在不同编程语言间的兼容性问题,因此最终采用了kryo作为序列化库。
使用场景:(数据交换或数据持久化)比如使用kryo把对象序列化成字节数组发送给消息队列或者放到redis等nosql中等等应用场景。
注意:由于kryo不是线程安全的,针对多线程情况下的使用,要对kryo进行一个简单的封装设计,从而可以多线程安全的使用序列化和反序列化
序列化和反序列化接口设计
- /**
 - * 序列化工具(程序调用该接口来实现obj<->byte[]之间的序列化/反序列化)
 - * @author eguid
 - *
 - */
 - public interface Serializer{
 - /**
 - * 序列化
 - * @param t
 - * @param bytes
 - */
 - public void serialize(Object t,byte[] bytes);
 - /**
 - * 序列化
 - * @param obj
 - * @param bytes
 - * @param offset
 - * @param count
 - */
 - public void serialize(Object obj, byte[] bytes, int offset, int count);
 - /**
 - * 反序列化
 - * @param bytes -字节数组
 - * @return T<T>
 - */
 - public <T>T deserialize(byte[] bytes);
 - /**
 - * 反序列化
 - * @param bytes
 - * @param offset
 - * @param count
 - * @return
 - */
 - public <T>T deserialize(byte[] bytes, int offset, int count);
 - }
 
使用kryo实现上面的接口
- /**
 - * 基于kyro的序列化/反序列化工具
 - *
 - * @author eguid
 - *
 - */
 - public class kryoSerializer implements Serializer {
 - // 由于kryo不是线程安全的,所以每个线程都使用独立的kryo
 - final ThreadLocal<Kryo> kryoLocal = new ThreadLocal<Kryo>() {
 - @Override
 - protected Kryo initialValue() {
 - Kryo kryo = new Kryo();
 - kryo.register(ct, new BeanSerializer<>(kryo, ct));
 - return kryo;
 - }
 - };
 - final ThreadLocal<Output> outputLocal = new ThreadLocal<Output>();
 - final ThreadLocal<Input> inputLocal = new ThreadLocal<Input>();
 - private Class<?> ct = null;
 - public kryoSerializer(Class<?> ct) {
 - this.ct = ct;
 - }
 - public Class<?> getCt() {
 - return ct;
 - }
 - public void setCt(Class<?> ct) {
 - this.ct = ct;
 - }
 - @Override
 - public void serialize(Object obj, byte[] bytes) {
 - Kryo kryo = getKryo();
 - Output output = getOutput(bytes);
 - kryo.writeObjectOrNull(output, obj, obj.getClass());
 - output.flush();
 - }
 - @Override
 - public void serialize(Object obj, byte[] bytes, int offset, int count) {
 - Kryo kryo = getKryo();
 - Output output = getOutput(bytes, offset, count);
 - kryo.writeObjectOrNull(output, obj, obj.getClass());
 - output.flush();
 - }
 - /**
 - * 获取kryo
 - *
 - * @param t
 - * @return
 - */
 - private Kryo getKryo() {
 - return kryoLocal.get();
 - }
 - /**
 - * 获取Output并设置初始数组
 - *
 - * @param bytes
 - * @return
 - */
 - private Output getOutput(byte[] bytes) {
 - Output output = null;
 - if ((output = outputLocal.get()) == null) {
 - output = new Output();
 - outputLocal.set(output);
 - }
 - if (bytes != null) {
 - output.setBuffer(bytes);
 - }
 - return output;
 - }
 - /**
 - * 获取Output
 - *
 - * @param bytes
 - * @return
 - */
 - private Output getOutput(byte[] bytes, int offset, int count) {
 - Output output = null;
 - if ((output = outputLocal.get()) == null) {
 - output = new Output();
 - outputLocal.set(output);
 - }
 - if (bytes != null) {
 - output.writeBytes(bytes, offset, count);
 - }
 - return output;
 - }
 - /**
 - * 获取Input
 - *
 - * @param bytes
 - * @param offset
 - * @param count
 - * @return
 - */
 - private Input getInput(byte[] bytes, int offset, int count) {
 - Input input = null;
 - if ((input = inputLocal.get()) == null) {
 - input = new Input();
 - inputLocal.set(input);
 - }
 - if (bytes != null) {
 - input.setBuffer(bytes, offset, count);
 - }
 - return input;
 - }
 - @SuppressWarnings("unchecked")
 - @Override
 - public <T> T deserialize(byte[] bytes, int offset, int count) {
 - Kryo kryo = getKryo();
 - Input input = getInput(bytes, offset, count);
 - return (T) kryo.readObjectOrNull(input, ct);
 - }
 - @Override
 - public <T> T deserialize(byte[] bytes) {
 - return deserialize(bytes, 0, bytes.length);
 - }
 
测试一下kryo的序列化和反序列化
为什么使用纳秒,而不用毫秒?与java原生的序列化反序列化要耗时几毫秒不同,kryo序列化和反序列化太快了,单个对象的序列化反序列化速度都在0.0x毫秒左右(如果电脑性能更好的话,会更快)
- Serializer ser = new kryoSerializer(Msg.class);
 - for (int i = 0; i < 10; i++) {
 - Msg msg = new Msg();
 - msg.setVersion_flag(new byte[] { 1, 2, 3 });
 - msg.setCrc_code((short) 1);
 - msg.setMsg_body(new byte[] { 123, 123, 123, 43, 42, 1, 12, 45, 57, 98 });
 - byte[] bytes = new byte[300];
 - long start = System.nanoTime();
 - ser.serialize(msg, bytes);
 - System.err.println("序列化耗时:" + (System.nanoTime() - start));
 - System.out.println(msg);
 - System.out.println(Arrays.toString(bytes));
 - Msg newmsg = null;
 - start = System.nanoTime();
 - newmsg = ser.deserialize(bytes);
 - System.err.println("反序列化耗时:" + (System.nanoTime() - start));
 - System.out.println(newmsg);
 - }
 
----end----
高性能的序列化与反序列化:kryo的简单使用的更多相关文章
- 利用php的序列化和反序列化来做简单的数据本地存储
		
利用php的序列化和反序列化来做简单的数据本地存储 如下程序可以做为一个工具类 /** * 利用php的序列化和反序列化来做简单的数据本地存储 */ class objectdb { private ...
 - XmlSerializer 对象的Xml序列化和反序列化
		
http://www.cnblogs.com/yukaizhao/archive/2011/07/22/xml-serialization.html 这篇随笔对应的.Net命名空间是System.Xm ...
 - XmlSerializer 对象的Xml序列化和反序列化,XMLROOT别名设置
		
这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间. 为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中 ...
 - Windows  phone 之XML序列化与反序列化
		
为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...
 - C#操作Xml:XmlSerializer 对象的Xml序列化和反序列化
		
这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间. 为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中的对 ...
 - XML的序列化和反序列化 详细介绍
		
为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...
 - C# Note4:XML序列化和反序列化(含加密解密等)
		
前言 在项目中,我们经常用到各种配置文件,比如xml文件.binary文件等等,这里主要根据实践经验介绍下xml文件的序列化和反序列化(毕竟最常用). 实践背景:我要做一个用户管理功能,用户账号信息存 ...
 - JAVA中序列化和反序列化中的静态成员问题
		
关于这个标题的内容是面试笔试中比较常见的考题,大家跟随我的博客一起来学习下这个过程. ? ? JAVA中的序列化和反序列化主要用于: (1)将对象或者异常等写入文件,通过文件交互传输信息: (2)将对 ...
 - C#序列化与反序列化方式简单总结
		
序列化和反序列化 相关类: System.SerializableAttribute特性(或称为属性), System.Runtime.Serialization.ISerializable(自定义序 ...
 
随机推荐
- Django之forms表单类
			
Form表单的功能 自动生成HTML表单元素 检查表单数据的合法性 如果验证错误,重新显示表单(数据不会重置) 数据类型转换(字符类型的数据转换成相应的Python类型) 1.创建Form类 from ...
 - 解决opencv无法读AVI视频的问题
			
原文来自:http://blog.csdn.net/yeqiu712/article/details/6220030 其实AVI只是一个外壳.里面的东西可不一样的! 问题:为什么我的电脑支持AVI或者 ...
 - POJ3009 Curling 2.0(DFS)
			
迷宫问题求最短路. 略有不同的是假设不碰到石头的话会沿着一个方向一直前进,出界就算输了.碰到石头,前方石头会消失,冰壶停在原地. 把这个当作状态的转移. DFS能够求出其最小操作数. #include ...
 - redis写磁盘报错Cannot allocate memory
			
查看 Redis 日志发现系统在频繁报错: [1821] 10 Nov 09:59:04.086 # Can't save in background: fork: Cannot allocate m ...
 - View数据呈现相关技术
			
一.了解Razor语法 1.Razor基本语法 a)输出单一变量时不需要加分号做结尾.如: <p>现在时刻:@DateTime.Now</p> b)输出一段含有空白字元或运算子 ...
 - ECMall验证码问题
			
一.确认问题: 输入下面这个地址:http://你的网址/index.php?app=captcha&876589486 打开后出现:mt_rand(): max(0) is smaller ...
 - Something Starts While Something Ends
			
(1)最终还是没能参加比赛,一次都没有机会. (2)有梦想,不到最后一刻不会放弃. (3)这里应该会搬次家,转到github上. (4)作为一个新手,什么东西都需要从头学起来,就从最基础的数据结构开始 ...
 - Linuxt图形界面安装
			
通常安装图形界面需要安装Xorg.桌面环境(Gnome.KDE.xfce等).字体等.你的Linux是什么版本?具体要看你的linux来决定用什么命令来安装. #yum grouplist 自己看看列 ...
 - Large-scale Incremental Processing Using Distributed Transactions and Notifications
			
Large-scale Incremental Processing Using Distributed Transactions and Notifications
 - PHP 格式化数字串
			
在xls或csv文件中, 超过12位以上的数字会被"科学计数", 所以当php读取这些文件的时候, 会读成 420E+16 , 显然这不是我们想要的, 所以就要用到数字格式化了! ...