高性能的序列化与反序列化:kryo的简单使用
前言:kryo是個(gè)高效的java序列化/反序列化庫,目前Twitter、yahoo、Apache、strom等等在使用該技術(shù),比如Apache的spark、hive等大數(shù)據(jù)領(lǐng)域用的較多。
為什么使用kryo而不是其他?
因?yàn)樾阅茏銐蚝谩1萲yro更高效的序列化庫就只有g(shù)oogle的protobuf了(而且兩者性能很接近),protobuf有個(gè)缺點(diǎn)就是要傳輸?shù)拿恳粋€(gè)類的結(jié)構(gòu)都要生成對應(yīng)的proto文件(也可以都放在同一個(gè)proto文件中,如果考慮到擴(kuò)展性的話,不建議放在一個(gè)proto文件中),如果某個(gè)類發(fā)生修改,還得重新生成該類對應(yīng)的proto文件;另外考慮到項(xiàng)目中用的全部是java技術(shù)棧,不存在不同編程語言間的兼容性問題,因此最終采用了kryo作為序列化庫。
使用場景:(數(shù)據(jù)交換或數(shù)據(jù)持久化)比如使用kryo把對象序列化成字節(jié)數(shù)組發(fā)送給消息隊(duì)列或者放到redis等nosql中等等應(yīng)用場景。
注意:由于kryo不是線程安全的,針對多線程情況下的使用,要對kryo進(jìn)行一個(gè)簡單的封裝設(shè)計(jì),從而可以多線程安全的使用序列化和反序列化
序列化和反序列化接口設(shè)計(jì)
/*** 序列化工具(程序調(diào)用該接口來實(shí)現(xiàn)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 -字節(jié)數(shù)組* @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實(shí)現(xiàn)上面的接口
/*** 基于kyro的序列化/反序列化工具* * @author eguid**/ public class kryoSerializer implements Serializer {// 由于kryo不是線程安全的,所以每個(gè)線程都使用獨(dú)立的kryofinal ThreadLocal<Kryo> kryoLocal = new ThreadLocal<Kryo>() {@Overrideprotected 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;}@Overridepublic void serialize(Object obj, byte[] bytes) {Kryo kryo = getKryo();Output output = getOutput(bytes);kryo.writeObjectOrNull(output, obj, obj.getClass());output.flush();}@Overridepublic 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并設(shè)置初始數(shù)組* * @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")@Overridepublic <T> T deserialize(byte[] bytes, int offset, int count) {Kryo kryo = getKryo();Input input = getInput(bytes, offset, count);return (T) kryo.readObjectOrNull(input, ct);}@Overridepublic <T> T deserialize(byte[] bytes) {return deserialize(bytes, 0, bytes.length);}測試一下kryo的序列化和反序列化
為什么使用納秒,而不用毫秒?與java原生的序列化反序列化要耗時(shí)幾毫秒不同,kryo序列化和反序列化太快了,單個(gè)對象的序列化反序列化速度都在0.0x毫秒左右(如果電腦性能更好的話,會(huì)更快)
轉(zhuǎn)載于:https://www.cnblogs.com/eguid/p/10195569.html
總結(jié)
以上是生活随笔為你收集整理的高性能的序列化与反序列化:kryo的简单使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 列表标签
- 下一篇: SFrame中的apple函数