2011年4月19日 星期二

phpcassa 初探

使用 NoSQL 的主要目的在於大量存取資料和負截平衡,查了 SimpleCassie 的官方網站,發現連線到 Cassandra 叢集的功能,還在待處理的列表之中。所以只好回頭去找一開始嘗試 Cassandra 時,看到的第一個 PHP 模組 phpcassa。

可能是 Cassandra 0.7.3 有 bug 或是其它的原因,總之第一次嘗試 phpcassa 的經驗是很讓人挫折的,這次不同的是,最基本我能夠肯定 Cassandra 和 phpcassa 也會用到的 Thrift 模組都是可運作的。這樣我就可以把重點放在 phpcassa 本身的語法或設定上。



來到官網,下載到目前最新的 0.7.a.4 版本,比上次測試的時候新。照著官網上的文件一行一行的輸入,首先載入對應的函數庫︰
require_once('phpcassa/connection.php');
require_once('phpcassa/columnfamily.php');
這部分沒有遇到什麼狀況,並沒有擔心可能遇到 PHP 5.3.x 不建議使用的函數

接著建立連線︰
$conn = new Connection('Keyspace1', array(
  array('host'=>'localhost', 'port'=>9160)
));
官網的指令中「localhost」前後是沒有單引號的,在 PHP 5.3.x 之前會被自動視為字串,不過在之後的版本則會將之視為語法錯誤,需要補上。

然後就得到另人意外的「Notice: The Connection class has been deprecated.」錯誤訊息,拒絕?我是照著範例輸的耶!?嘗試忽略它輸入後續的程式,只會得到執行期例外並強制終止程式進行,並沒有解決問題,只好東找西找其它可能的原因。

後來在下載下來的程式碼,看到 doc 資料夾裡面有個叫「README.mkd」的檔案,打開後找到答案。原來 Connection 的使用方式已經不再被使用,取而代之的是另一個叫 ConnctionPool 的類別,輸入的參數和 Connection 也有小小差異,少了一層 array 包覆。因此修改後的程式變成︰
$conn = new ConnectionPool('Keyspace1', array('localhost'));
$cf = new ColumnFamily($conn, 'Columnfamily1');
「Keyspace1」和「Columnfamily1」要自行代換成實際存在的名稱。

接著,就可以使用 $cf 裡的 get() 和 insert() 方法,方法當中並沒有 edit() 或 update() 方法,只要用 insert() 對同一個 column key 存入儲,就可以取代原來的資料,另外很高興的發現,原來使用 SimpleCassie 遇到資料無法修改的問題也沒有了!

不過,另人想不透的是, phpcassa 花費的時間實在是太久了一些,撰寫程式用兩個模組作測試,發現同樣建立連線, SimpleCassie 只要花費 3.6 毫秒,  phpcassa 卻要花費 4 秒,超過 1000 倍!而讀取資料的速度兩者相差則是沒有太大的差距。所以接著就解決連線建立的問題,否則每次連線建立要花費 4 秒,我想沒有人會有耐心對它進行資料查詢。

一開始假設,也許是因為連線建立時,需要經過很多的檢查、測試工作,所以如果能夠避開連線的重新建立,應該可以大量減少需要的時間。因此我試著把整個物件序列化放到 $_SESSION 裡面,當有資料在 $_SESSION 裡,就直接拿來使用。

實測的結果,序列化反解回的物件仍然可以使用,至少短時間內不會有連線失敗的問題,不過花費的時間由原來的 4 秒暴增 2.5 倍變成 10 秒多,就讓人無言了。

正打算回頭查不知道正確比例多少的官方文件前,胡裡胡塗的被我找到解決方式。把原來的
$conn = new ConnectionPool('Keyspace1', array('localhost'));
改成
$conn = new ConnectionPool('Keyspace1', array('127.0.0.1));
就可以讓連線建立由 4 秒 變成 6毫秒,雖然還是比 SimpleCassie 慢,不過已經到了可以讓人接受的水準了。猜想可能是把 localhost 轉換成 IP 位置的過程出了問題,不過還不確定是 phpcassa 的問題,還是系統的 hosts 設定沒設好。

接下來應該就是連線到多台主機,和大量存/取資料的效能測試了…

沒有留言:

張貼留言