標籤:

scylladb專欄開篇

scylladb專欄開篇

來自專欄 scylladb

自2018/4/16開啟scylladb專欄後,相繼有些知友關注了,想著是不是也應該寫點什麼來開啟scylladb&seastar專欄的寫作(總不能想著等我先研究幾年再來寫吧 →_→ , 本身也是個不斷漸進的學習過程)。由於項目需求,接觸scylla/seastar半年有餘,了解有限,但還是挺喜歡這個方面的,打算堅持寫下去。

scylla/seastar由Avi Kivity(以前沒聽說過,現在知道了,KVM開發者,大牛級人物)團隊於2015年開始開發,已在github開源。seastar風格很別緻,以前倒沒見過C++能寫成這樣的;由seastar構建的Scylladb據官方說比Cassandra強上10倍,當然這不僅僅是語言本身的結果,但這吸引著我想去探討其內在的原理。

關於seastar

簡單說,它是一個基於future/promise的C++ 14(官方宣稱是14,但就編譯情況和commit message來看已經是17了,且boost用的也是很新的版本)事件驅動非同步處理框架。從C++11開始標準就已經支持future,只不過據說不好用,缺少很多語義支持或者處於experimental狀態,也許這也導致facebook做了擴展future功能的事,體現在了很有名的folly庫里。seastar中future的用法和folly中future已經有幾分相似了,比如都有then的級聯調用,支持when_all semantics等。

但無疑seastar功能更強,它最大限度地利用硬體特性和避免現有缺陷:

  • 嫌傳統TCP棧處理開銷大,那就弄個用戶TCP棧或者支持DPDK;
  • 嫌linux IO schduler性能弱,就弄個user-space IO scheduler,自己管理IO請求和分配優先順序,且繞過page cache,直接DMA傳輸;
  • 覺得flush, compaction等後台任務佔用過多IO帶寬就發明個workload conditioning機制,可簡單理解為database內部進行自動調優,使得對客戶端請求時延不受過多影響;
  • 當然還有更多優秀特性如memory lsa, cpu scheduler等待挖掘……

在筆者開始研究seastar之前,試圖找找除了源碼中自帶的memcached, httpd應用,業界還有沒有seastar的應用,貌似只找到由阿里同學 @Jaco 及團隊所寫的pedis,這款產品被scylla官方在keynote中多次引用,也作為了它們宣傳seastar的一個good example。改日也抽空看看pedis,分享一下。

關於scylla

簡單講,它是基於seastar框架而對java寫的cassandra的翻版,當然未來的發展很可能不再是翻版而是強烈的擴展,官方在keynote上說可以把它看成是the power of cassandra at the speed of redis。關於性能如何,大家可進入官網註冊,用它提供的test drive感受半小時,會有測試報告生成[我的測試報告]。

更詳細的介紹可進youtube觀看官方keynotes

  • ScyllaDB- It takes more than C++14 to become next gen C++
  • Scylla Summit 2017- NEXTGEN NoSQL Keynote

如果以前研究過cassandra,那麼對於scylla的概念理解會方便很多,畢竟兼容,很多詞用得都一樣,像column_family, LSM, partition, tombstone等意義都相同。但如果不熟悉,那就稍微麻煩點,筆者建議可先學習一下datastax上關於cassandra的文檔,datastax上的文檔相當豐富,相信一定會很有收穫

強烈推薦的cassandra書籍:Cassandra The Definitive Guide

學習網站:datastax , thelastpickle blog

論壇:google group 上的scylla-dev, scylla-user, seastar-dev

當然從文檔入手了解cassandra只是手段,如果你關注scylla,就不要把過多時間沉迷在其java源碼上了,它可與c++寫的風格上差得不是一點點,參考意義不大。當然scylla官方博客不容錯過,會有很多技術文章分享。

這裡大概說說scylla 2.0(目前版本兼容cassandra 2.1,還有很長一段路要走,見官方roadmap)實現的大概樣子:

在main啟動時會創建各種頂層對象如database, cql_server, storage_proxy, query_processor等,很多對象都是通過seastar的模板類distributed<>來分布在各個cpu上(官方叫shard),因此是lock-free,沒有lock contention,也就是所謂的share-nothing架構,各CPU有各自的數據結構,互不影響,如果要通信可以發message;

客戶端通過cql,一種和sql類似但功能有限查詢語言,與cql_server通信。有認證、parse、execute等action,但不像RDMS那樣有query tree, execution plan;

底層存儲是以Log-structured merge tree,對寫非常友好,純append-only,讀操作稍微麻煩點,需要將sstable, memtable的相關item進行合併,有cache當然會更快;刪除的item以tombstone形式存儲,舊版本的數據會定期被後台任務compaction所清理

目前write path, read path還沒有達到cassandra 文檔所描述的那樣,比如key_cache並沒有,也許未來會支持

目前學習到的knowledge

  • 筆者對c++只是較為熟悉,沒有個十年都不敢自稱是精通。但通過一段時間對scylla/seastar代碼的了解,對modern c++有了更多認識,現在叫我去看c++ 11以前的legacy code,總有種衝動想把它改造成基於c++ 14/17的版本
  • 對於future/promise, lambda的編程有了更多體會,基於future的非同步機制功能很強大,但編程難度確是挺大,一不小心就可能漏到了某個case,畢竟各個事件在時間上是並行的,你無法肯定到底哪個事件在哪個事件前完成,所以scylla代碼里常見的一種編碼風格是用bool類型+if判斷和promise來同步事件。一個地方set true,然後在另一個地方檢測事件是否發生或完成, 或者一個地方get_future(),另一個地方set_value();

    至於要不要在代碼中大量使用lambda,可能這就仁者見仁了,會有人覺得可讀性很差,我的傾向是儘可能地用,注意縮進,也不是那麼難閱讀;另外,lambda與functional programming很有關聯,雖說在c++中用函數式編程不如專門的函數式語言那麼自然,但這種範式很經典,可以嘗試在c++中使用

  • 源碼中大量使用橋接模式,即定義一個抽象implementation介面,然後針對不同情況派生出不同的impl,以模板參數包在Client對象里,有很大靈活性,不過貌似代碼有所冗餘;visitor模式也有所使用

開篇就這樣吧。關於seastar/scylla有趣的特性有很多,細節再抽空分享,希望能給大家帶來乾貨。有不對的地方,望請指正~

附上scylla開發團隊照片(Cloudius Systems),向優秀工程師致敬~


推薦閱讀:

我們為什麼需要HBase?
Python爬取妹子,哇!太多了,看不過來了,我一個G的硬碟要滿了
如何在node項目中引入redis做session持久化?
時間序列數據的存儲和計算 - 開源時序資料庫解析(一)
酷站推薦 - neo4j.com - The Neo4j Graph Platform

TAG:NoSQL |