在 NoSQL 陣營中,Cassandra 和 HBase 這兩個同樣受到 BigTable 啓發,但踏上不一樣道路的近親,常被放在一起比較。兩者當然都各有優缺點,也都還在各自進化中,本文並不打算觸及這些爭論,只談談 Cassandra 的 cluster 設定。
Cassandra 部署起來很簡單。由於每一個節點都可以扮演幾乎完全相同的角色,不僅避開 SPOF 問題,更簡化了部署的複雜度,不必像 HBase 還得仰賴 ZooKeeper 等外來援兵(當然啦,如果你本來就打算用上整個 Hadoop 重砲,那就不能算是缺點了)。
部署起來有多簡單?看這位老兄秀的 “How to set up a 4 node Cassandra cluster in under 2 minutes” 影片,就知道有多神了。
儘管理論上是這樣沒錯,但魔鬼藏在細節裡,還是有一些地方要留意一下。
Hotspots
前一陣子將 Cassandra 部署到兩台主機,實際運作兩周後,發現兩台主機的負載極度不平衡:
% nodetool status
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns Host ID Rack
UN xx.xx.xx.xx 9.51 GB 1 99.9% xxxxxxxxxx rack1
UN yy.yy.yy.yy 8.58 GB 1 0.1% yyyyyyyyyy rack1
在 "Owns" 那一欄呈現出很誇張的情況⋯⋯
分散式系統的直覺告訴我,如果沒有其他可疑之處,應該要先試著朝 consistent hashing 的方向去處理。
上網搜尋一下,找到(理論上)應該是正解的資訊:
- 原理:Ring Management
- 官方工具:Token Generating Tool
照著上述文件,執行 token-generator
,並依序回答問題:
% token-generator
Token Generator Interactive Mode
--------------------------------
How many datacenters will participate in this Cassandra cluster? 1
How many nodes are in datacenter #1? 2
DC #1:
Node #1: 0
Node #2: 85070591730234615865843651857942052864
然後,將 token-generator
的輸出,填入 Cassandra 設定檔 cassandra.yaml
的 initial_token
欄⋯⋯結果還是沒有改善。
一陣亂試亂試,試到最後居然連 Cassandra 都開不起來了⋯⋯
怒⋯⋯
兇手在這裡
隔天,回頭逐行檢視設定檔 cassandra.yaml
內容,突然發現 Cassandra 1.2 預設的 “partitioner” 居然是 Murmur3Partitioner
,而不是之前在網路上或書本上常常提到的 RandomPartitioner
。官方說帖是:
RandomPartitioner distributes rows across the cluster evenly by md5. This is the default prior to 1.2 and is retained for compatibility.
Murmur3Partitioner is similar to RandomPartioner but uses Murmur3_128 hash function instead of md5. When in doubt, this is the best option.
The Murmur3Partitioner provides faster hashing and improved performance than the previous default partitioner (RandomPartitioner).
「呃,剛剛用的官方工具 token-generator
好像只有針對 RandomPartitioner
來計算?」
的確如此,看它的 help,完全沒有這個參數:
% token-generator --help
Usage: token-generator <nodes_in_dc1> [<nodes_in_dc2> [...]]
Given a list of numbers indicating the number of nodes in each separate
datacenter, outputs a recommended list of tokens to use with
RandomPartitioner: one for each node in each datacenter.
Options:
-h, --help show this help message and exit
--ringrange=RINGRANGE
Specify a numeric maximum token value for your ring,
different from the default value of 2^127.
--graph Show a rendering of the generated tokens as line
segments in a circle, colored according to datacenter
-n, --nts Optimize multi-cluster distribution for
NetworkTopologyStrategy [default]
-o, --onts Optimize multi-cluster distribution for
OldNetworkTopologyStrategy
--test Run in test mode, outputting an HTML file to display
various generated ring arrangements.
「嗯,會不會就是因為這樣,所以才不適用?因為它根本不認得 Murmur3Partitioner
⋯⋯」
「咦,這不是官方欽定的工具嗎?怎麼會這麼顧慮不周,沒有隨之改版升級呢⋯⋯」
針對 Murmur3Partitioner 重新計算
於是,改用 Cassandra 1.2 官方文件 “Generating Tokens” 所介紹的公式:
% python -c 'print [str(((2**64 / number_of_tokens) * i) - 2**63) for i in range(number_of_tokens)]'
用 2
代入 number_of_tokens
,得到一組數字:
% python -c 'print [str(((2**64 / 2) * i) - 2**63) for i in range(2)]'
['-9223372036854775808', '0']
不想把 initial_token
寫死在設定檔 cassandra.yaml
裡面,因此,我改用 nodetool move
命令來設定:
% nodetool -h xx.xx.xx.xx move \\-9223372036854775808
% nodetool -h yy.yy.yy.yy move 0
再看一次這兩台主機的負載情況變得如何了:
% nodetool status
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Owns Host ID Token Rack
UN xx.xx.xx.xx 66.39 KB 50.0% xxxxxxxxxx -9223372036854775808 rack1
UN yy.yy.yy.yy 65.41 KB 50.0% yyyyyyyyyy 0 rack1
嗯,"Owns" 那一欄正常多了!
Cassandra Token Calculator
網路上有人寫了一份 Cassandra Token Calculator,可以讓你任意指定要用 Murmur3Partitioner 還是 RandomPartioner,很方便。
順手試了一下 Murmur3Partitioner 的輸出,因為,照流量成長的趨勢看來,搞不好很快就需要用到這份小抄了⋯⋯ :D
2 nodes:
- -9223372036854775808
- 0
3 nodes:
- -9223372036854775808
- -3074457345618258603
- 3074457345618258602
4 nodes:
- -9223372036854775808
- -4611686018427387904
- 0
- 4611686018427387904
5 nodes:
- -9223372036854775808
- -5534023222112865485
- -1844674407370955162
- 1844674407370955161
- 5534023222112865484