yuandong| 2015.05.11
作為主要和磁碟、網路打交道的分布式儲存系統,序列化是最基礎的功能之一,今天我們來看一下ceph中序列化的設計與實現。
1 ceph序列化的方式
序列化(ceph稱之為encode)的目的是將資料結構表示為二進位製流的方式,以便通過網路傳輸或儲存在磁碟等儲存介質上,其逆過程稱之為反序列化(ceph稱之為decode)。 例如對於字串「abc」,其序列化結果為8個位元組(bytes):
03 00 00 00 61 62 63
其中頭四個位元組(03 00 00 00)表示字串的長度為3個字元,後3個位元組(61 62 63)分別是字元「abc」的ascii碼的16進製表示。 ceph採用little-endian的序列化方式,即低位址存放最低有效位元組,所以32位整數0x12345678的序列化結果為78 56 34 12。
由於序列化在整個系統中是非常基本,非常常用的功能,ceph將其序列化方式設計為乙個同一的結構,即任意支援序列化的資料結構,都必須提供一對定義在全域性命名空間上的序列化/反序列化(encode/decode)函式。例如,如果我們定義了乙個結構體inode,就必須在全域性命名空間中定義以下兩個方法:
encode(struct inode, bufferlist bl);在此基礎上,序列化的使用就變得非常容易 。 即對於任意可序列化的型別t的例項instance_t,都可以通過以下語句:decode(struct inode, bufferlist::iterator bl);
::encode(instance_t, instance_bufferlist);
將instance_t序列化並儲存到bufferlist類的例項instance_bufferlist中。
以下**演示了將乙個時間戳以及乙個inode序列化到乙個bufferlist中。
utime_t timestamp;序列化後的資料可以通過反序列化方法讀取,例如以下**片段從乙個bufferlist中反序列化乙個時間戳和乙個inode(前提是該bl中已經被序列化了乙個utime_t和乙個inode,否則會報錯)。inode_t inode;
bufferlist bl;
::encode(timetamp, bl)
::encode(inode, bl);
bufferlist::iterator bl;2 資料結構的序列化ceph為其所有用到資料型別提供了序列化方法或反序列化方法,這些資料型別包括了絕大部分基礎資料型別(int、bool等)、結構體型別的序列化(ceph_mds_request_head等)、集合型別(vector、list、set、map等)、以及自定義的複雜資料型別(例如表示inode的inode_t等),以下分別介紹不同資料型別的序列化實現方式。::decode(timetamp, bl)
::decode(inode, bl);
2.1 基本資料型別的序列化
基本資料型別的序列化結果基本就是該型別在記憶體中的表示形式。基本資料型別的序列化方法使用手工編寫,定義在include/encoding.h中,包括以下型別:
在手工編寫encode方法過程中,為了避免重複**,借助了write_raw_encoder和write_inttype_encoder兩個巨集。
2.2 結構體型別的序列化
結構體型別的序列化方法與基本資料型別的序列化方法一致,即使用結構體的記憶體布局作為序列化的形式。在結構體定義完成後,通過呼叫write_raw_encoder巨集函式生成結構體的全域性encode方法,例如結構體ceph_mds_request_head相關結構實現如下。
struct ceph_mds_request_head __attribute__ ((packed));
write_raw_encoder(ceph_mds_request_head)其中:
template2.3 集合資料型別的序列化集合資料型別序列化的基本思路包括兩步:inline void encode_raw(const t& t, bufferlist& bl)
template
inline void decode_raw(t& t, bufferlist::iterator &p)
序列化集合大小,
序列化集合內的所有元素
例如vector& v的序列化方法:
template其中元素的序列化通過呼叫該元素的encode方法實現。inline void encode(const std::vector& v, bufferlist& bl)
常用集合資料型別的序列化已經由ceph實現,位於include/encoding.h中,包括以下集合型別:
集合型別的序列化方法皆為基於泛型(模板類)的實現方式,適用於所有泛型派生類。
2.4 複雜資料型別的序列化
除以上兩種業務無關的資料型別外,其它資料型別的序列化實現包括兩部分:
在型別內部現實encode方法,
將型別內部的encode方法重定義為全域性方法。
以下以utime_t類為例:
class utime_t tv;utime_t內部實現了encode和decode兩個方法,write_class_encoder巨集函式將這兩個方法轉化為全域性方法。void encode(bufferlist &bl) const
void decode(bufferlist::iterator &p) };
write_class_encoder(utime_t)
write_class_encoder巨集函式定義於include/encoding.h中,其定義如下:
#define write_class_encoder(cl)
inline void encode(const cl &c, bufferlist &bl, uint64_t features=0)
inline void decode(cl &c, bufferlist::iterator &p)
複雜資料結構內部的encode方法的實現方式通常是呼叫其內部主要資料結構的encode方法,例如utime_t類的encode方法實際上是序列化內部的tv.tv_sec和tv.tv_nsec兩個成員。
序列化(序列化)
原書上翻譯為序列化,msdn翻譯為序列化 作用 當需要儲存,或者網路傳輸 remoting時,資料 物件或值 需要序列化 類似於打包傳輸檔案。system.serializableattribute 序列化是指儲存和獲取磁碟檔案 記憶體或其他地方中的物件。在序列化時,所有的例項資料都儲存到儲存介質上...
序列化(模型序列化 序列化巢狀)
from rest framework import serializers from meituan.models import merchant,class merchantserializer serializers.modelserializer class meta model merch...
Python中的序列化和反序列化
python中的序列化和反序列化通常有兩種模組的使用 1 pickle模組 2 json模組 1 序列化 就是把不可傳輸的物件轉換為可儲存或可傳輸的過程 2 反序列化 就是把在磁碟,等介質中的資料轉換為物件 描述 對於大多數應用程式來講,dump 和load 函式的使用就是你使用pickle模組所需...