天天看點

高可用分布式非關系型資料庫-Cassandra

1 理論基礎

1.1 簡介

Apache Cassandra是一套開源分布式NoSQL資料庫系統。它最初由Facebook開發,用于儲存收件箱等簡單格式資料,集Google BigTable的資料模型與Amazon Dynamo的完全分布式架構于一身。Facebook于2008将Cassandra開源,此後,由于Cassandra良好的可擴充性和性能,被Apple Comcast Instagram Spotify eBay Rackspace Netflix等知名網站所采用,成為了一種流行的分布式結構化資料存儲方案。

在資料庫排行榜“DB-Engines Ranking”中,Cassandra排在第七位,是非關系型資料庫中排名第二高的(僅次于MongoDB)。

- 可彈性擴充性,允許根據需求增加節點滿足更多的用戶端請求

- 業務高可用性,架構具有容災設計避免單點故障造成業務中斷

- 線性規模性能,吞吐量随着節點數量的增加而呈線性增長

- 靈活資料存儲,可滿足所有資料格式,包括結構化,半結構化和非結構化且可動态調整資料結構

- 輕松資料分發,通過在多個資料中心複制資料,提供靈活的分布資料

1.2 系統架構

1.2.1 架構目标

- 分擔多個節點之間的大資料負載

- 避免單點故障

1.2.2 架構特點

- 群集中的角色都相同,每個節點互相獨立但同時與其他節點互連

- 群集中的每個節點都可以接受讀取和寫入請求,而無需理會資料在群集中的實際位置

- 當單點故障發生時,用戶端可以從群集中的其他非故障節點中提取或寫入資料

1.3.3 資料複制

<a href="https://s4.51cto.com/wyfs02/M01/97/84/wKioL1kvabqwZiegAAAzdE59xUk921.jpg" target="_blank"></a>

- Cassandra群集使用Gossip協定在節點間互相通訊和檢測群集中的故障節點

- 群集中一或多個節點充當資料供給,如有過期節點Cassandra将最新資料傳回給用戶端并修複過期節點

1.3.4 關鍵部件介紹

- Node,指構成群集的成員伺服器

- Data Center,群集中相關可用節點的集合

- Cluster,群集包含一個或多個資料中心

- Commit Lot,寫入操作之前的記錄日志,群集依賴日志做崩潰恢複。

- MemTable,駐留在記憶體中的資料結構,Commit Log後資料将寫入到MemTable

- SSTable,當達到設定門檻值,資料将從MemTable批量重新整理到磁盤中存為SSTable

- Bloom filter,

 -- 二進制向量資料結構,它具有很好的空間和時間效率,

 -- 被用來檢測一個元素是不是集合中的一個成員。

 -- 如果檢測結果為是,該元素不一定在集合中;

 -- 但如果檢測結果為否,該元素一定不在集合中。

1.3.5 資料寫入流程

- 先記錄日志(CommitLog)後寫入資料

- 資料先寫入到Column Family對應的Memtable中

- Memtable達到一定量時再批量重新整理磁盤中存為SSTable

注:相當于緩存寫回機制,它将随機IO轉成順序IO(降低存儲壓力)

1.4 資料模型

1.4.1 Colume

<a href="https://s2.51cto.com/wyfs02/M00/97/76/wKioL1kujBTwMXyrAAAbXv0spso648.png" target="_blank"></a>

列是Cassandra中最小的資料單元,由以下元素組成:

- Name,唯一名稱,用于引用列

- Value,列的内容,可以是不同的類型,如AsciiType,LongType,TimeUUIDType,UTF8Type等。

- TimeStamp,時間戳記,用于确定有效内容的系統時間戳

範例如下:

Name

Value

TimeStamp

"age"

"18"

1270694041669000

"height"

"172cm"

注:一行為一個Colume

1.4.2 Super Column

<a href="https://s4.51cto.com/wyfs02/M00/97/81/wKiom1kvWHHT_U3uAABIN1sRAGs042.png" target="_blank"></a>

超級列相當于Column的數組或集合,由Super Column name和一個或多個的Column構成。

Super Column Name

Columns

StudentA

"20"

1.4.3 Column Family

列族是一個NoSQL的對象(相當于關系型資料庫的表),它包含描述對象屬性的相關Column或Super Column。

列族分類:

- 普通列族,以列來描述族的屬性

- 超級列族,以超級列來描述族的屬性

Column Family Key

1.4.4 KeySpace

鍵空間是Cassandra中資料的最外層容器,其基本屬性有,

- Replication factor,叢集中将接收相同資料副本的計算技術

- Replica placement strategy,定義環中的複制政策

 -- simple strategy,簡單政策

 -- old network topology strategy,舊網絡拓撲政策

 -- network topology strategy,網絡拓撲政策

- Column families,列族(包含一個或多個列族)

1.4.5 總資料模型圖

<a href="https://s3.51cto.com/wyfs02/M00/97/69/wKiom1kuUyGR-FZ3AAAt9iquY4g970.gif" target="_blank"></a>

2 實踐部分

2.1 環境資訊

HostName = cassandra0[1-2].cmdschool.org

ipAddress = 10.168.0.5[1-2]

OS = CentOS 7.3 x86_64

2.2 JDK安裝

2.2.1 下載下傳JDK包

In cassandra0[1-2]:

1

2

<code>cd</code> <code>~</code>

<code>wget http:</code><code>//download</code><code>.oracle.com</code><code>/otn/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-linux-x64</code><code>.</code><code>tar</code><code>.gz?AuthParam=1495873209_eea482e2b59774918c970cf5dc383fdb</code>

注:如需其他版本請參閱,http://www.oracle.com/technetwork/java/javase/archive-139210.html

2.2.2 建立java目錄

<code>mkdir</code> <code>/usr/java</code>

2.2.3 解壓

<code>tar</code> <code>xf jdk-8u121-linux-x64.</code><code>tar</code><code>.gz</code>

<code>mv</code> <code>jdk1.8.0_121/ </code><code>/usr/java/</code>

2.2.4 配置環境變量

<code>vim </code><code>/etc/profile</code><code>.d</code><code>/java</code><code>.sh</code>

加入如下内容:

3

4

<code>export</code> <code>JAVA_HOME=</code><code>/usr/java/jdk1</code><code>.8.0_121</code>

<code>export</code> <code>JRE_HOME=${JAVA_HOME}</code><code>/jre</code>

<code>export</code> <code>CLASSPATH=.:${JAVA_HOME}</code><code>/lib</code><code>:${JRE_HOME}</code><code>/lib</code>

<code>export</code> <code>PATH=${JAVA_HOME}</code><code>/bin</code><code>:$PATH</code>

2.2.5 配置生效

<code>source</code> <code>/etc/profile</code>

2.2.6 環境變量測試

<code>java -version</code>

2.3 安裝Cassandra

2.3.1 先決條件檢查

1)JAVA檢查

 java -version

顯示如下:

<code>java version </code><code>"1.8.0_121"</code>

<code>Java(TM) SE Runtime Environment (build 1.8.0_121-b13)</code>

<code>Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)</code>

2)python檢查:

<code>python --version</code>

<code>Python 2.7.5</code>

2.3.2 下載下傳安裝包

<code>wget https:</code><code>//mirrors</code><code>.tuna.tsinghua.edu.cn</code><code>/apache/cassandra/3</code><code>.10</code><code>/apache-cassandra-3</code><code>.10-bin.</code><code>tar</code><code>.gz</code>

2.3.3 解壓安裝包

<code>tar</code> <code>-xf apache-cassandra-3.10-bin.</code><code>tar</code><code>.gz</code>

2.3.4 部署到程式目錄

<code>mkdir</code> <code>/usr/cassandra</code>

<code>mv</code> <code>apache-cassandra-3.10 </code><code>/usr/cassandra/</code>

2.3.5 配置運作使用者

<code>useradd</code> <code>-s </code><code>/sbin/nologin</code> <code>-b </code><code>/var/lib</code> <code>cassandra</code>

<code>chown</code> <code>-R cassandra:cassandra </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code>

<code>chmod</code> <code>-R 770 </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code>

确認使用者資料目錄存在:

<code>ls</code> <code>-ld </code><code>/var/lib/cassandra/</code>

<code>drwx------. 6 cassandra cassandra 136 Jun  1 09:42 </code><code>/var/lib/cassandra/</code>

2.3.6 配置環境變量

1)環境變量配置

<code>vim </code><code>/etc/profile</code><code>.d</code><code>/cassandra</code><code>.sh</code>

加入如下配置:

<code>export</code> <code>CASSANDRA_HOME=</code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code>

<code>export</code> <code>CASSANDRA_PATH=${CASSANDRA_HOME}</code><code>/bin</code>

<code>export</code> <code>PATH=${CASSANDRA_PATH}:$PATH</code>

2)使環境變量生效

3)測試環境變量

<code>cassandra -</code><code>v</code>

<code>3.10</code>

2.3.7 配置Cassandra的環境變量

<code>cp</code> <code>-a </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/bin/cassandra</code><code>.</code><code>in</code><code>.sh </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/bin/cassandra</code><code>.</code><code>in</code><code>.sh.default</code>

<code>vim </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/bin/cassandra</code><code>.</code><code>in</code><code>.sh</code>

啟用并修改如下配置:

<code># JAVA_HOME can optionally be set here</code>

<code>JAVA_HOME=</code><code>/usr/java/jdk1</code><code>.8.0_121</code>

注:提示“Cassandra 3.0 and later require Java 8u40 or later.”時需要配置

2.4 配置Cassandra群集

2.4.1 環境變量配置

<code>cp</code> <code>-a </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/conf/cassandra</code><code>.yaml </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/conf/cassandra</code><code>.yaml.default</code>

<code>vim </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/conf/cassandra</code><code>.yaml</code>

修改如下配置:

In cassandra01:

5

6

7

8

9

10

11

<code>cluster_name: </code><code>'Cassandra Cluster'</code>

<code>seed_provider:</code>

<code>- seeds: </code><code>"10.168.0.51,10.168.0.52"</code>

<code>listen_address:  10.168.0.51</code>

<code>rpc_address: 10.168.0.51</code>

<code>start_rpc: </code><code>true</code>

<code>data_file_directories:</code>

<code>    </code><code>- </code><code>/var/lib/cassandra/data</code>

<code>commitlog_directory: </code><code>/var/lib/cassandra/commitlog</code>

<code>saved_caches_directory: </code><code>/var/lib/cassandra/saved_caches</code>

In cassandra02:

<code>listen_address:  10.168.0.52</code>

<code>rpc_address: 10.168.0.52</code>

注:seeds的配置允許隻寫其他節點的IP,不寫本機IP。

2.4.2 配置cassandra-env環境腳本

<code>cp</code> <code>-a </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/conf/cassandra-env</code><code>.sh </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/conf/cassandra-env</code><code>.sh.default</code>

<code>vim </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/conf/cassandra-env</code><code>.sh</code>

修改配置如下:

<code>MAX_HEAP_SIZE=</code><code>"1G"</code>

<code>HEAP_NEWSIZE=</code><code>"256M"</code>

2.5 防火牆配置

<code>firewall-cmd --permanent --add-port 7000</code><code>/tcp</code>

<code>firewall-cmd --permanent --add-port 9042</code><code>/tcp</code>

<code>firewall-cmd --reload</code>

<code>firewall-cmd --list-all</code>

2.6 服務的控制

2.6.1 測試服務啟動

<code>sudo</code> <code>-u cassandra </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/bin/cassandra</code> <code>-f</code>

看到如下資訊則服務正常啟動:

<code>INFO  [Thread-2] 2017-06-01 10:51:47,640 ThriftServer.java:133 - Listening </code><code>for</code> <code>thrift clients...</code>

注:按下[Ctrl+C]可結束程序

2.6.2 确認服務正常啟動

<code>pgrep -u cassandra -f cassandra</code>

顯示PID如下:

<code>2596</code>

2.6.3 檢查群集的狀态

<code>nodetool status</code>

資訊顯示如下:

<code>Datacenter: datacenter1</code>

<code>=======================</code>

<code>Status=Up</code><code>/Down</code>

<code>|/ State=Normal</code><code>/Leaving/Joining/Moving</code>

<code>--  Address      Load       Tokens       Owns (effective)  Host ID                               Rack</code>

<code>UN  10.168.0.51  213.63 KiB  256          100.0%            6faefd3b-e2cf-4477-a1c1-922d4f10b7a5  rack1</code>

<code>UN  10.168.0.52  103.69 KiB  256          100.0%            3cc4fdd7-53a0-4a67-be7f-fbe1cd8d0571  rack1</code>

2.6.4 測試連接配接

<code>cqlsh -ucassandra -pcassandra 10.168.0.51</code>

<code>cqlsh -ucassandra -pcassandra 10.168.0.52</code>

2.6.5 結束程序

<code>pkill -f cassandra</code>

2.6.6 配置服務控制腳本

<code>vim </code><code>/etc/init</code><code>.d</code><code>/cassandrad</code>

輸入如下内容:

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

<code>#!/bin/bash</code>

<code># chkconfig: 2345 55 25</code>

<code>user=</code><code>"cassandra"</code>

<code>status() {</code>

<code>        </code><code>if</code> <code>[ ! `pgrep -u $user -f cassandra | </code><code>wc</code> <code>-l` -</code><code>eq</code> <code>0 ]; </code><code>then</code>

<code>                </code><code>echo</code> <code>"statusChecking for service cassandra running"</code>

<code>                </code><code>exit</code> <code>0</code>

<code>        </code><code>else</code>

<code>                </code><code>echo</code> <code>"statusChecking for service cassandra not running"</code>

<code>                </code><code>exit</code> <code>1</code>

<code>        </code><code>fi</code>

<code>}</code>

<code>start() {</code>

<code>        </code><code>if</code> <code>[ `pgrep -u $user -f cassandra | </code><code>wc</code> <code>-l` -</code><code>eq</code> <code>0 ]; </code><code>then</code>

<code>                </code><code>sudo</code> <code>-u $user </code><code>/usr/cassandra/apache-cassandra-3</code><code>.10</code><code>/bin/cassandra</code> <code>&gt; </code><code>/dev/null</code>

<code>                </code><code>for</code> <code>((i=60; i&gt;=0; i--)) </code><code>do</code>

<code>                        </code><code>sleep</code> <code>1s</code>

<code>                        </code><code>if</code> <code>[ ! `pgrep -u $user -f cassandra | </code><code>wc</code> <code>-l` -</code><code>eq</code> <code>0 ]; </code><code>then</code>

<code>                                </code><code>echo</code> <code>"start service cassandra finish"</code>

<code>                                </code><code>break</code> <code>&amp; </code><code>exit</code> <code>0</code>

<code>                        </code><code>fi</code>

<code>                        </code><code>if</code> <code>[ $i -</code><code>eq</code> <code>0 ]; </code><code>then</code>

<code>                                </code><code>echo</code> <code>"start service cassandra failed"</code>

<code>                                </code><code>exit</code> <code>1</code>

<code>                </code><code>done</code>

<code>stop() {</code>

<code>                </code><code>pgrep -u $user -f cassandra | </code><code>xargs</code> <code>kill</code> <code>-9</code>

<code>                </code><code>for</code><code>((i=60; i&gt;=0; i--)) </code><code>do</code>

<code>                        </code><code>if</code> <code>[ `pgrep -u $user -f cassandra | </code><code>wc</code> <code>-l` -</code><code>eq</code> <code>0 ]; </code><code>then</code>

<code>                                </code><code>echo</code> <code>"stop service cassandra finish"</code>

<code>                                </code><code>echo</code> <code>"stop service cassandra failed"</code>

<code>case</code> <code>"$1"</code> <code>in</code>

<code>        </code><code>start)</code>

<code>                </code><code>start</code>

<code>        </code><code>;;</code>

<code>        </code><code>stop)</code>

<code>                </code><code>stop</code>

<code>        </code><code>restart)</code>

<code>        </code><code>status)</code>

<code>                </code><code>status</code>

<code>        </code><code>*)</code>

<code>                </code><code>echo</code> <code>"Usage: $0 {start|stop|restart|status}"</code>

<code>esac</code>

2.6.7 配服務自動啟動和啟動服務

<code>chkconfig cassandrad on</code>

<code>/etc/init</code><code>.d</code><code>/cassandrad</code> <code>start</code>

=====================================

本文轉自 tanzhenchao 51CTO部落格,原文連結:http://blog.51cto.com/cmdschool/1930284,如需轉載請自行聯系原作者