zoukankan      html  css  js  c++  java
  • 高性能的序列化与反序列化: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进行一个简单的封装设计,从而可以多线程安全的使用序列化和反序列化

    序列化和反序列化接口设计

    1. /**
    2. * 序列化工具(程序调用该接口来实现obj<->byte[]之间的序列化/反序列化)
    3. * @author eguid
    4. *
    5. */
    6. public interface Serializer{
    7. /**
    8. * 序列化
    9. * @param t
    10. * @param bytes
    11. */
    12. public void serialize(Object t,byte[] bytes);
    13. /**
    14. * 序列化
    15. * @param obj
    16. * @param bytes
    17. * @param offset
    18. * @param count
    19. */
    20. public void serialize(Object obj, byte[] bytes, int offset, int count);
    21. /**
    22. * 反序列化
    23. * @param bytes -字节数组
    24. * @return T<T>
    25. */
    26. public <T>T deserialize(byte[] bytes);
    27. /**
    28. * 反序列化
    29. * @param bytes
    30. * @param offset
    31. * @param count
    32. * @return
    33. */
    34. public <T>T deserialize(byte[] bytes, int offset, int count);
    35. }

    使用kryo实现上面的接口

    1. /**
    2. * 基于kyro的序列化/反序列化工具
    3. *
    4. * @author eguid
    5. *
    6. */
    7. public class kryoSerializer implements Serializer {
    8. // 由于kryo不是线程安全的,所以每个线程都使用独立的kryo
    9. final ThreadLocal<Kryo> kryoLocal = new ThreadLocal<Kryo>() {
    10. @Override
    11. protected Kryo initialValue() {
    12. Kryo kryo = new Kryo();
    13. kryo.register(ct, new BeanSerializer<>(kryo, ct));
    14. return kryo;
    15. }
    16. };
    17. final ThreadLocal<Output> outputLocal = new ThreadLocal<Output>();
    18. final ThreadLocal<Input> inputLocal = new ThreadLocal<Input>();
    19. private Class<?> ct = null;
    20. public kryoSerializer(Class<?> ct) {
    21. this.ct = ct;
    22. }
    23. public Class<?> getCt() {
    24. return ct;
    25. }
    26. public void setCt(Class<?> ct) {
    27. this.ct = ct;
    28. }
    29. @Override
    30. public void serialize(Object obj, byte[] bytes) {
    31. Kryo kryo = getKryo();
    32. Output output = getOutput(bytes);
    33. kryo.writeObjectOrNull(output, obj, obj.getClass());
    34. output.flush();
    35. }
    36. @Override
    37. public void serialize(Object obj, byte[] bytes, int offset, int count) {
    38. Kryo kryo = getKryo();
    39. Output output = getOutput(bytes, offset, count);
    40. kryo.writeObjectOrNull(output, obj, obj.getClass());
    41. output.flush();
    42. }
    43. /**
    44. * 获取kryo
    45. *
    46. * @param t
    47. * @return
    48. */
    49. private Kryo getKryo() {
    50. return kryoLocal.get();
    51. }
    52. /**
    53. * 获取Output并设置初始数组
    54. *
    55. * @param bytes
    56. * @return
    57. */
    58. private Output getOutput(byte[] bytes) {
    59. Output output = null;
    60. if ((output = outputLocal.get()) == null) {
    61. output = new Output();
    62. outputLocal.set(output);
    63. }
    64. if (bytes != null) {
    65. output.setBuffer(bytes);
    66. }
    67. return output;
    68. }
    69. /**
    70. * 获取Output
    71. *
    72. * @param bytes
    73. * @return
    74. */
    75. private Output getOutput(byte[] bytes, int offset, int count) {
    76. Output output = null;
    77. if ((output = outputLocal.get()) == null) {
    78. output = new Output();
    79. outputLocal.set(output);
    80. }
    81. if (bytes != null) {
    82. output.writeBytes(bytes, offset, count);
    83. }
    84. return output;
    85. }
    86. /**
    87. * 获取Input
    88. *
    89. * @param bytes
    90. * @param offset
    91. * @param count
    92. * @return
    93. */
    94. private Input getInput(byte[] bytes, int offset, int count) {
    95. Input input = null;
    96. if ((input = inputLocal.get()) == null) {
    97. input = new Input();
    98. inputLocal.set(input);
    99. }
    100. if (bytes != null) {
    101. input.setBuffer(bytes, offset, count);
    102. }
    103. return input;
    104. }
    105. @SuppressWarnings("unchecked")
    106. @Override
    107. public <T> T deserialize(byte[] bytes, int offset, int count) {
    108. Kryo kryo = getKryo();
    109. Input input = getInput(bytes, offset, count);
    110. return (T) kryo.readObjectOrNull(input, ct);
    111. }
    112. @Override
    113. public <T> T deserialize(byte[] bytes) {
    114. return deserialize(bytes, 0, bytes.length);
    115. }

    测试一下kryo的序列化和反序列化

    为什么使用纳秒,而不用毫秒?与java原生的序列化反序列化要耗时几毫秒不同,kryo序列化和反序列化太快了,单个对象的序列化反序列化速度都在0.0x毫秒左右(如果电脑性能更好的话,会更快)

    1. Serializer ser = new kryoSerializer(Msg.class);
    2. for (int i = 0; i < 10; i++) {
    3. Msg msg = new Msg();
    4. msg.setVersion_flag(new byte[] { 1, 2, 3 });
    5. msg.setCrc_code((short) 1);
    6. msg.setMsg_body(new byte[] { 123, 123, 123, 43, 42, 1, 12, 45, 57, 98 });
    7. byte[] bytes = new byte[300];
    8. long start = System.nanoTime();
    9. ser.serialize(msg, bytes);
    10. System.err.println("序列化耗时:" + (System.nanoTime() - start));
    11. System.out.println(msg);
    12. System.out.println(Arrays.toString(bytes));
    13. Msg newmsg = null;
    14. start = System.nanoTime();
    15. newmsg = ser.deserialize(bytes);
    16. System.err.println("反序列化耗时:" + (System.nanoTime() - start));
    17. System.out.println(newmsg);
    18. }
    ----end----










  • 相关阅读:
    算法与数据结构基础
    算法与数据结构基础
    算法与数据结构基础
    算法与数据结构基础
    算法与数据结构基础
    算法与数据结构基础
    最佳实践 根据状态操作,这样能避免吃掉异常
    最佳实践 状态设计
    Android HTTPS如何10分钟实现自签名SSL证书
    马桶选购
  • 原文地址:https://www.cnblogs.com/jpfss/p/9771363.html
Copyright © 2011-2022 走看看