2015-10-26 100 views
1

我將大塊日誌數據存儲在memcache中,以便稍後將其扔入數據庫。在對服務器的每個請求中,我使用memcached :: append()保存一組數據,使用換行符來分隔塊。一個簡化的版本是這樣的:分隔二進制數據塊

$myCache->append('log', serialize($myArray)."\n"); 

後來,當我要建立可查詢我拉所有行從數據庫中和反序列化每一個:

$dataToInsert = explode("\n", $myCache->get('log')); 
$dataToInsert = array_map(function($row) { 
    return unserialize($row); 
}, $dataToInsert); 

也能正常工作與構建在serialize()和unserialize()中,但我想利用igbinary的明顯優勢 - 大小和速度。不幸的是,當我替換函數的igbinary版本時,出現錯誤。

看來,igbinary-序列化的數據可以包含「\ n」字符,所以當我爆炸存儲的數據時,它會創建部分行,當然會失敗。

除了換行符以外,我還可以使用分隔符來區分igbinary數據塊,還是igbinary和append()從根本上不兼容?

+0

你可以嘗試下劃線'_',只是因爲它自然不是一個分隔符,所以可能工作...沒有測試過,但沒有做過,但probs值得一試。 – AdamJeffers

+0

當我說二進制數據包含換行符時,我有點不確切;因爲它是二進制的,它根本沒有字符。但是explode()會將任何'0A'解釋爲換行符。我想我的問題歸結爲:'是否有任何字節組合不在我可以爆炸的二進制數據中?或者也許除了爆炸()用來檢索離散數據塊的方法? – Jerry

回答

1

由於igbinary存儲binary data as-is,因此不能保證任何字符可供使用:您可以序列化包含任何字節的字符串或整數,任何字符。

memcached支持添加,刪除和替換數據以及更新字符串。

兩種方式,以保持記錄的數據出來的記憶和memcached的,直到SQL查詢浮現在腦海中:

  • 使用多個鍵:'log1',...,'logN'並跟蹤N
  • 通過轉義序列化的二進制輸出(並在反序列化之前消除)保留一個字符。

預約可以做這樣的:

str_replace("\n", "\n1", $data) . "\n0" 

這將確保有每一次的輸出\n, 它後跟一個01

我不跟\n\n更換\n,因爲這將無法正常工作,如果$data的開始或結束\n

所以:

$myCache->append('log', str_replace("\n", "\n1", igbinary_serialize($myArray)."\n0"); 

拆分然後將數據使用\n0做的,而\n1被轉義回\n

$dataToInsert = explode("\n0", $myCache->get('log')); 
$dataToInsert = array_map(function($row) { 
    return igbinary_unserialize(str_replace("\n1", "\n", $row)); 
}, $dataToInsert); 
+0

完美。謝謝!我已經開始編寫代碼來對每個二進制數據塊進行長度前綴,但是這樣感覺更好。 – Jerry

+0

這可能會更快,更高效。我認爲你的解決方案是最好的答案:-) – Kenney