顯示具有 centos 標籤的文章。 顯示所有文章
顯示具有 centos 標籤的文章。 顯示所有文章

2017年2月19日 星期日

Cassandra Cluster Tutorial


壹、前言

寫這篇文的原因與心得可以用同一句話來述說:「千萬不要無腦rm -rf 。」不小心把整個環境的東西刪除的下場就是只能全部從來一遍,就趁這個機會紀錄一下環境的設定以免之後又發生一樣的事。

貳、安裝環境

1. 作業系統:CentOS7
2. 節點數量:4
centos02: 192.168.1.2 (使用這台作為seed node)
centos03: 192.168.1.3
centos04: 192.168.1.4
centos05: 192.168.1.5
3. Cassandra版本:DataStax Distribution of Apache Cassandra 3.2
註:使用這個版本的原因如Cassandra Tutorial - 安裝篇這篇文所說,在這邊就不再贅述,但是有一點很重要,官方版本的Cassandra在目前(20170220)已經更新到3.10了,Datastax也不再提供版本的更新與維護,因此對於使用新版本的人這篇文章或許不是很能符合你的需求,在參考前可能會需要注意一下。

參、步驟

1. 修改Cassandra設定檔
設定檔預設是放在 /etc/cassandra/conf/cassandra.yaml

修改第10行
cluster_name: 'Test Cluster'
cluster中的每個實體都必須使用相同設定

修改第343行
- seeds: "127.0.0.1"
將所有節點的 - seeds: "127.0.0.1" 設定為 seed node 的 ip,讓他們知道在加入 cluster 時(只有在加入當下才需要)要從哪一台電腦取得其他節點的資訊,此外 seed 可以一個以上,如果有超過一個 seed 的話,ip 以逗號隔開,例如 "<ip>,<ip>,<ip>"。
在本例中設定為 - seeds: "192.168.1.2"

修改第472行
listen_address: localhost
Cassandra內部在溝通資料時使用的ip就在這邊設定 (Cassandra's internal storage protocol uses the listen_address.),因此所有節點皆要將之設為自己的 ip 或 hostname ,以便讓其他節點知道傳送資料時知道要送到哪裡去,如果是設定為 hostname 的話,所有節點的 /etc/hostname, /etc/hosts 或 DNS 等皆要進行設定。
centos02>>listen_address: 192.168.1.2
centos03>>listen_address: 192.168.1.3
centos04>>listen_address: 192.168.1.4
centos05>>listen_address: 192.168.1.5

修改第546行
rpc_address: localhost
Client端與server溝通時 (Thrift RPC service and native transport) 使用的地址
centos02>>rpc_address: 192.168.1.2
centos03>>rpc_address: 192.168.1.3
centos04>>rpc_address: 192.168.1.4
centos05>>rpc_address: 192.168.1.5

註:之後如果要使用cqlsh的話必須在後面接上想要連接的server的ip才可以用,例如cqlsh 192.168.1.4


到這裡cassandra.yaml的設定就算完成了 ^_^

    2. 啟動cluster
    因為所有node在啟動時都會先與seed溝通,因此必須先啟動seed node,啟動完seed node後再啟動其他節點

    # service cassandra start

    之後可以檢查cluster節點的狀態
    #nodetool status

    由下圖可以發現我們的四個節點都已經成功地彼此連接了!

    2016年12月21日 星期三

    解決CentOS無法掛載(mount) NTFS檔案系統設備的問題

    今天想要複製檔案到隨身碟時發現插下去怎麼沒有反應,雖然可以顯示隨身碟已經插上電腦,但要進行讀寫時出現了一大串錯誤訊息,但是可以看到裡面有這麼一句話
    Error mounting: mount: unknown filesystem type 'ntfs'
    原來CentOS不能辨識NTFS這個檔案系統的東西阿,搜尋後發現需要安裝ntfs-3g才能正常存取這種檔案系統,安裝方法如下
    #yum install ntfs-3g

    然後系統顯示
    No package ntfs-3g available.
    Error: Nothing to do
    居然從yum裡面找不到,原來要從epel裡面才找的到阿。

    補充:EPEL (Extra Packages for Enterprise Linux) 是一個由 Fedora Special Interest Group 社群所維護的套件庫,其主要目的是提供各種企業級的 Linux 一些額外的高品質套件,這個套件庫可用於RHEL、CentOS、Scientific Linux 與Oracle Linux。

    正確的安裝方法如下
    先安裝EPEL套件包
    #yum install -y epel-release

    安裝以EPEL以後就可以用yum安裝ntfs-3g囉
    #yum install -y ntfs-3g

    安裝完以後,如果將來需要掛載NTFS檔案格式的設備時就不會再發生問題了!

    2016年12月20日 星期二

    輕鬆解決 VirtualBox is already locked by a session (or being locked or unlocked)

    話說前幾天實驗室跳電,雖然伺服器會自己重開機,但虛擬機並不會跟著重開(懶得設定的下場),遠端開啟虛擬機的指令如之前的文章所述

    $VBoxManage startvm centos03

    在正常情況下,執行成功應該會出現這個訊息
    Waiting for VM "centos03" to power on...
    VM "centos03" has been successfully started.
    但是這次的執行出現的卻是
    VBoxManage: error: The machine 'centos03' is already locked by a session (or being locked or unlocked)
    VBoxManage: error: Details: code VBOX_E_INVALID_OBJECT_STATE (0x80bb0007), component MachineWrap, interface IMachine, callee nsISupports
    VBoxManage: error: Context: "LaunchVMProcess(a->session, sessionType.raw(), env.raw(), progress.asOutParam())" at line 589 of file VBoxManageMisc.cpp
    那要怎麼解決呢?先試試看最白癡的方法直接重開好了,反正也沒再跑甚麼東西,因此我們執行關閉虛擬機指令

    $ VBoxManage controlvm centos03 poweroff

    正常的情況下應該會出現
    0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
    但在這個例子中出現的卻是
    VBoxManage: error: Invalid machine state: Starting (must be Running, Paused or Stuck)
    VBoxManage: error: Details: code VBOX_E_INVALID_VM_STATE (0x80bb0002), component ConsoleWrap, interface IConsole, callee nsISupports
    VBoxManage: error: Context: "PowerDown(progress.asOutParam())" at line 231 of file VBoxManageControlVM.cpp
    現在是甚麼情況?開也開不了關也關不了,怎麼辦呢?這時候只要執行只下命令就好

    $ VBoxManage startvm centos03 --type emergencystop

    這條指令不會聽出任何提示訊息,執行完就直接關閉虛擬機器,因此我們隨後可以直接再次開啟這台虛擬機器就解決囉

    2016年11月13日 星期日

    How to install VirtualBox on CentOS 7 using command line


    前言


    最近已經將資料庫在練習的環境測試完了,接下來就該用實驗室的電腦做一點比較正式的環境架設了,但最怕麻煩的我怎麼可能乖乖蹲在實驗室架設環境呢?來回實驗室要快半小時耶,瘋了喔這麼累,在家裡躺在床上用SSH(Secure Shell)遠端實驗室電腦才是王道阿,網路上大多數的教學都是教大家如何在圖形化介面下安裝與設定虛擬機器,這對我這種懶人來說太麻煩了,所以誕生了一個寫一個完全使用command line來安裝VirtualBox教學的念頭,作為小懶人間的小小交流。
      因為平常習慣用的是CentOS,所以下面的指令皆用建立CentOS虛擬機為例。


    步驟


    Step1:安裝虛擬機器

    由於Yum預設的伺服器中並沒有內建VirtualBox軟體庫(Repository)的相關資訊,因此我們必須自己建立一個VirtualBox的repo檔,並安裝目前最新版(20161107)的VirtualBox。
    #cd /etc/yum.repos.d
    #wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo
    #yum install -y VirtualBox-5.1.x86_64

    Step2:建立虛擬機器

    #VBoxManage createvm --name centos
    createvm:建立一個虛擬機器檔案
    --name後面加虛擬機器的名字
    這個命令在執行成功後會在你的家目錄底下建立VirtualBox VMs/centos/centos.vbox

    Step3:幫虛擬機器建立硬碟檔案

    #VBoxManage createhd --filename centos --size 1000
    createhd:建立硬碟
    --filename後面加上剛剛建立的虛擬機器檔名
    --size是硬碟大小,以MB(Megabyte)為單位,100MB只是示範使用

    Step4:讓VirtualBox找到你的虛擬機器檔案

    #VBoxManage registervm '/home/user/VirtualBox VMs/centos/centos.vbox'
    registervm後面接虛擬機器檔案的完整路徑,前後用引號圈起來
    (其實也可以在createvm階段就進行這個操作,只要在filename打完後,空一格加上--register就好,但因為個人習慣才把這個步驟在這個階段進行。)

    Step5:虛擬機器的更多設定

    #VBoxManage modifyvm centos --ostype RedHat_64 --memory 512 --vram 10 --accelerate3d on --audio alsa --audiocontroller ac97 --nic1 nat --nictype1 82540EM --cableconnected1 on
    modifyvm後面接虛擬機器的名稱,讓你對指定虛擬機器進行更多設定
    --ostype在使用圖形化介面版本新增虛擬機器時,有沒有印象有一欄是要選擇虛擬機器類型?
    那個步驟就是在這邊進行,注意使用的系統是不是64位元的,像我使用的是64位元的CentOS 7,因此我的類型是輸入RedHat_64 (底下會附上比較常見的幾種,如果使用的作業系統沒有在底下看到可以執行$VBoxManage list ostypes查閱。)
    --memory 設定給予虛擬機器的記憶體大小,記憶體大小以MB(Megabyte)為單位,512MB只是示範使用。
    --vram 顯示記憶體大小,記憶體大小以MB(Megabyte)為單位,10MB只是示範使用
    --accelerate3d 是否啟動3D加速
    --audio後接主機的音效驅動程式,可以選擇的有none, null, oss, alsa , pulse
    --audiocontroller後接音效晶片,可以選擇的有ac97, hda, sb16(這部分還不確定理解是否正確)
    --nic後面不用空格接上網路卡編號(1~n),之後空格接上模式,可以選擇的有none, null, nat, bridged, intnet, hostonly, vde
    --nictype後面不用空格接上網路卡編號(1~n),之後空格接上網路卡的類型,可以選擇的選項有Am79C970A, Am79C973, 82540EM, 82543GC, 82545EM, virtio
    --cableconnected後面不用空格接上網路卡編號(1~n),選擇是否連接

    作業系統與ostype對照
    Debian (32-bit)----->Debian
    Debian (64-bit)----->Debian_64
    Fedora (32-bit)----->Fedora
    Fedora (64-bit)----->Fedora_64
    Red Hat (32-bit)--->RedHat
    Red Hat (64-bit)--->RedHat_64
    Ubuntu (32-bit)---->Ubuntu
    Ubuntu (64-bit)---->Ubuntu_64
    FreeBSD (32-bit)-->FreeBSD
    FreeBSD (64-bit)-->FreeBSD_64

    Step8:設定虛擬機的儲存設備連接埠

    首先我想新增一個IDE給虛擬機器連接光碟機
    $VBoxManage storagectl centos --name IDE --add ide --controller PIIX4 --bootable on
    再新增一個SATA給虛擬機器連接硬碟
    $VBoxManage storagectl centos --name SATA --add sata --controller IntelAhci --bootable on
    storagectl後面加上目標虛擬機器的名稱
    --name可以讓你幫這個儲存裝置命名,你要想取啥甚至連Trump都行
    --add後面接上你的介面,可以選擇的有ide, sata, scsi, floppy
    --controller後接的為控制晶片,可以選擇的有LsiLogic, LSILogicSAS, BusLogic, IntelAhci, PIIX3, PIIX4, ICH6, I82078(對這方面較沒研究,因此在這邊都選擇最常見的,IDE對PIIX4,SATA對IntelAhci)
    --bootable選擇on讓他可以啟動

    Step9:將儲存設備接上虛擬機器

    設定虛擬機器連接埠所連接的對象(硬碟),並且放入虛擬機器的硬碟檔案
    #VBoxManage storageattach centos --storagectl SATA --port 0 --device 0 --type hdd --medium /home/user/VirtualBox\ VMs/centos/centos.vdi
    設定虛擬機器連接埠所連接的對象(光碟機),並且放入虛擬機器的光碟檔案
    #VBoxManage storageattach centos --storagectl IDE --port 0 --device 0 --type dvddrive --medium /home/user/CentOS-7-x86_64-Everything-1511.iso
    storageattach後面接目標虛擬機器
    --storagectl後面接剛剛透過--name所命名的連接埠
    --port儲存設備接上的port
    --device設定該裝置在該port上的編號
    --type後接該儲存設備的型態,可以使用的有dvddrive, hdd, fdd
    --medium後接上欲放入的檔案完整路徑

    Step10:啟動
    經過10個步驟的摧殘,終於可以啟動與關閉虛擬機器了
    #VBoxManage startvm centos
    #VBoxManage controlvm centos poweroff

    總結


      以上就是如何在Linux安裝、設定並且啟動虛擬機器的方法,如果要遠端重灌的話,需要開啟遠端桌面伺服器VRDE,這部分還沒有時做過,因此不在本文章中討論。

    2016年6月19日 星期日

    MongoDB Sharding Cluster Tutorial

    壹、環境

    因為是只是練習環境,我開了4台虛擬機 (com6, com7, com8, com9) 進行測試
    作業系統皆為CentOS 7
    com6: 192.168.1.1
    com7: 192.168.1.2
    com8: 192.168.1.3
    com9: 192.168.1.4


    貳、Sharding Cluster構想

    預計由三組Replica Set,一個Config Server,一個Routing Server (mongos) 組成
    因此
    com6: ("rs0/192.168.1.1:27017,192.168.1.1:27018,192.168.1.1:27019")
    com7: ("rs1/192.168.1.2:27017,192.168.1.2:27018,192.168.1.2:27019")
    com8: ("rs2/192.168.1.3:27017,192.168.1.3:27018,192.168.1.3:27019")
    com9: Config Server: ("192.168.1.4:27017") , Routing Server: ("192.168.1.4:27018")


    參、步驟

    一、安裝MongoDB

    1. MongoDB的官方軟體庫包含有五個軟體包(packages)
    (1) mongodb-org                  這是一個metapackage,可以透過安裝這個自動安裝其他四個軟體包
    (2) mongodb-org-server       mongod伺服器與設定檔
    (3) mongodb-org-mongos    mongos伺服器.
    (4) mongodb-org-shell         mongo操作介面(shell)

    (5) mongodb-org-tools         包括了所有跟mognodb有關的小工具

    2. 因為CentOS預設的Yum伺服器中沒有MongoDB軟體庫(Repository)的相關資訊,因此必須先新增Repos設定檔
    #vi /etc/yum.repos.d/mongodb-org-3.2.repo
    [mongodb-org-3.4]
    name=MongoDB Repository
    baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
    gpgcheck=1
    enabled=1
    gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
    3. 新增完之後就可以使用Yum安裝了
    #yum install –y mongodb-org


    二、設定MongoDB


    在構想階段,有com6, com7 com8分別為三個MongoDB實體的Replica Set,因此設定設定檔、資料庫目錄、記錄檔共要三組
    而com9為Config Server與Routing Server所以設定檔跟記錄檔要兩份,但Routing Server本身不儲存任何資料,因此只需要替Config Server建立一個資料庫目錄即可

    1.  複製設定檔
    com6, com7, com8 都要執行以下指令,將設定檔複製三分,分別為mongod1.conf, mongod2.conf, mongod3,conf
    #mv /etc/mongod.conf /etc/mongod1.conf
    #cp /etc/mongod1.conf /etc/mongod2.conf
    #cp /etc/mongod1.conf /etc/mongod3.conf

    com9裡面有兩個MongoDB實體,因此要兩份設定檔,分別為mongod-configserv.conf與mongod-routingserv.conf
    #mv /etc/mongod.conf /etc/mongod-configserv.conf
    #cp /etc/mongod1.conf /etc/mongod-routingserv.conf

    2. 修改設定檔

    2.1. com6, com7, com8設定
    #vim /etc/mongod1.conf
    修改將第10行的path: /var/log/mongodb/mongod.log
    將com6的mongod.log改為mongod1.log
    將com7的mongod.log改為mongod1.log
    將com8的mongod.log改為mongod1.log

    修改第14行的dbPath: /var/lib/mongo
    將com6的mongo改為dbPath: /var/lib/mongo1
    將com7的mongo改為dbPath: /var/lib/mongo1
    將com8的mongo改為dbPath: /var/lib/mongo1


    註解第29行的bindIp: 127.0.0.1
    將com6的bindIp註解起來,變為#bindIp
    將com7的bindIp註解起來,變為#bindIp
    將com8的bindIp註解起來,變為#bindIp

    取消第36#replication的註解
    將com6的#replication: 取消註解,變成replication: 
    將com7的#replication: 取消註解,變成replication: 
    將com8的#replication: 取消註解,變成replication: 

    在第37行新增Replica Set的名稱(  replSetName: )
    com6為  replSetName: rs0
    com7為  replSetName: rs1
    com8為  replSetName: rs2
    注意:replSetName前面空兩格,:後面空一格,不然會報錯

    #vim /etc/mongod2.conf
    修改將第10行的path: /var/log/mongodb/mongod.log
    將com6的mongod.log改為mongod2.log
    將com7的mongod.log改為mongod2.log
    將com8的mongod.log改為mongod2.log

    修改第14行的dbPath: /var/lib/mongo
    將com6的mongo改為dbPath: /var/lib/mongo2
    將com7的mongo改為dbPath: /var/lib/mongo2
    將com8的mongo改為dbPath: /var/lib/mongo2

    修改第28行的port: 27017
    com6改為port: 27018
    com7改為port: 27018

    com8改為port: 27018


    註解第29行的bindIp: 127.0.0.1
    將com6的bindIp註解起來,變為#bindIp
    將com7的bindIp註解起來,變為#bindIp
    將com8的bindIp註解起來,變為#bindIp

    取消第36#replication的註解
    將com6的#replication: 取消註解,變成replication: 
    將com7的#replication: 取消註解,變成replication: 
    將com8的#replication: 取消註解,變成replication: 

    在第37行新增Replica Set的名稱(  replSetName: )
    com6為  replSetName: rs0
    com7為  replSetName: rs1
    com8為  replSetName: rs2
    注意:replSetName前面空兩格,:後面空一格,不然會報錯


    #vim /etc/mongod3.conf
    修改將第10行的path: /var/log/mongodb/mongod.log
    將com6的mongod.log改為mongod3.log
    將com7的mongod.log改為mongod3.log
    將com8的mongod.log改為mongod3.log

    修改第14行的dbPath: /var/lib/mongo
    將com6的mongo改為dbPath: /var/lib/mongo3
    將com7的mongo改為dbPath: /var/lib/mongo3
    將com8的mongo改為dbPath: /var/lib/mongo3

    修改第28行的port: 27017
    com6改為port: 27019
    com7改為port: 27019

    com8改為port: 27019


    註解第29行的bindIp: 127.0.0.1
    將com6的bindIp註解起來,變為#bindIp
    將com7的bindIp註解起來,變為#bindIp
    將com8的bindIp註解起來,變為#bindIp

    取消第36#replication的註解
    將com6的#replication: 取消註解,變成replication: 
    將com7的#replication: 取消註解,變成replication: 
    將com8的#replication: 取消註解,變成replication: 

    在第37行新增Replica Set的名稱(  replSetName: )
    com6為  replSetName: rs0
    com7為  replSetName: rs1
    com8為  replSetName: rs2
    注意:replSetName前面空兩格,:後面空一格,不然會報錯

    2.2. com9設定

    2.2.1. config server
    #vim mongo-config.conf
    將第10行的path: /var/log/mongodb/mongod 改為path: /var/log/mongodb/mongod-configserv.log
    將第14行的dbPath: /var/lib/mongo改為 dbPath: /var/lib/mongo-configserv
    將第29行的bindIp: 127.0.0.1註解掉,改為#bindIp:  127.0.0.1
    將第38行的#sharding取消註解,變為sharding
    在第39行打上  clusterRole: configsvr
    (clusterRole前面空兩格,:後空一格,不然會報錯)

    2.2.2. routing server(mongos)
    #vim /etc/mongo-routingserv.conf
    將第10行的path: /var/log/mongodb/mongod 改為path: /var/log/mongodb/mongod-routingserv.log
    將13~16行的與storage與旗下之選項全部註解掉
    將第28行的,port:  27017改為port:  27018
    將第29行的bindIp: 127.0.0.1註解掉,改為#bindIp:  127.0.0.1
    將第38行的#sharding取消註解,變為sharding
    在第39行打上  configDB: 192.168.1.4:27017
    帶第40行打上  chunkSize: 64
    (configDB與chunkSize前面空兩格,:後面空一格,不然會報錯)

    3. 建立資料庫目錄

    3.1. com6, com7, com8
    #mv /var/lib/mongo /var/lib/mongo1
    #mkdir mongo2
    #mkdir mongo3
    #chown mongod:mongod mongo2
    #chown mongod:mongod mongo3


    3.2. com9
    #mv /var/lib/mongo /var/lib/mongo-configserv

    三、建立Sharding Cluster

    1. 建立Replica Set

    1.1. 啟動mongod
    在com6, com7, com8都要執行mongod
    #mongod -f /etc/mongod1.conf
    #mongod -f /etc/mongod2.conf
    #mongod -f /etc/mongod3.conf
    -f 的意思是使用設定檔執行,後面接設定檔路徑

    1.2. 初始化Replica Set
    假設三組Replica Set皆要以使用27017這個port的mongod作為為Primary
    在com6, com7, com8執行mongo客戶端
    #mongo --port 27017
    --port後面接的port是mongod設定檔中的設定port
    所以如果是打27018就是連入使用mongod2.conf這個設定檔的mongod

    分別在三台電腦中輸入
    >rs.initiate()
    輸入完之後如果有顯示{“ok” : 1}表示設定成功
    會看到你的輸入欄位由>變為rs0:OTHER>
    過幾秒按一下Enter會發現rs0:OTHER>變為rs0>PRIMARY,此時可以知道這個mongod在Replica Set的地位已經是Primary

    1.3. 替mongod加入新成員
    在com6中輸入
    rs.0:PRIMARY>rs.add(”192.168.1.1:27018”)
    rs.0:PRIMARY>rs.add(”192.168.1.1:27019”)
    顯示{“ok” : 1}表示新增成功

    在com7中輸入
    rs.0:PRIMARY>rs.add(”192.168.1.2:27018”)
    rs.0:PRIMARY>rs.add(”192.168.1.2:27019”)
    顯示{“ok” : 1}表示新增成功

    在com8中輸入
    rs.0:PRIMARY>rs.add(”192.168.1.3:27018”)
    rs.0:PRIMARY>rs.add(”192.168.1.3:27019”)
    顯示{“ok” : 1}表示新增成功

    新增成功後可以輸入rs.status()查看Replica Set查看狀態

    2. Sharding Cluster設定

    2.1. 在com9中啟動config server與mongos
    #mongod -f /etc/mongod-configserv.conf
    #mongos -f /etc/mongod-routingserv.conf

    2.2. 將Replica Set轉為Shard

    2.2.1. 進入mongos
    #mongo --port 27018

    2.2.2. 將Replica Set加入Sharding Cluster中

    輸入
    mongos>sh.shardAdd("rs0/192.168.1.1:27017,192.168.1.1:27018,192.168.1.1:27019”)
    回傳{ "shardAdded" : "rs0", "ok" : 1 }代表成功
    mongos>sh.shardAdd("rs1/192.168.1.2:27017,192.168.1.2:27018,192.168.1.2:27019”)
    回傳{ "shardAdded" : "rs1", "ok" : 1 }代表成功
    mongos>sh.shardAdd("rs2/192.168.1.3:27017,192.168.1.3:27018,192.168.1.3:27019”)
    回傳{ "shardAdded" : "rs2", "ok" : 1 }代表成功

    新增完成後可以輸入
    mongos>sh.status()
    檢視sharding cluster狀態

    做到這邊有三組ReplicaSet作為Shard的Sharding Cluster就建立成功了!!
    (導入資料進入Sharding Cluster時,要導入到mongos中)

    肆、測試成果

    一、Replica Set測試

    1. 檢查否有容錯轉移的功能,以rs0為例

    關閉Primary的mongod
    #mongod -f /etc/mongod1.conf --shutdown

    連入使用原先為Primary的mongod
    #mongo --port 27017

    出現類似以下訊息表示已經成功關閉
    exception: connect failed
    此時在連上原先為Secondary的mongod
    #mongo --port 27018
    可以發現輸入指令的地方從原先的 rs0:SECONDARY> 變為 rs0:PRIMARY>

    此時再重新啟動剛剛關閉的mongod
    #mongod -f /etc/mongod1.conf

    連上該mongod
    #mongo --port 27017
    可以發現輸入指令的地方從原先的 rs0:Primary> 變為 rs0:Secondary>

    此時輸入
    rs0:SECONDARY>rs.status()
    可以發現使用port27018的mongod的"stateStr"已經由"SECONDARY"變為"PRIMARY"
    而可以使用port27017的mongod的"stateStr"已經由"PRIMARY"變為"SECONDARY"

    證明這個Replica Set具有容錯轉移功能

    二、檢查資料是否會正常複製

    1. 下載MongoDB所提供的資料及進行測試
    #wget https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json

    2. 將資料集導入mongod中

    #mongoimport --port 27017 --db rstest --collection restaurants --file primer-dataset.json
    (只能將資料導入PRIMARY中,在這個例子中,PRIMARY還是port27017這個mongod)

    3. 進入PRIMARY
    #mongo --port27017

    4. 進入導入的資料庫
    rs1:PRIMARY>use rstest

    5. 查看資料表是否有導入成功
    rs1:PRIMARY>show collections
    有顯示restaurants表示導入成功

    6. 查看資料表內容
    rs1:PRIMARY>db.restaurants.find()

    7.離開mongo shell
    方法a: Ctrl+C
    方法b: rs1:PRIMARY>exit

    7. 看看其他Replica Set中的mongod是否有相同的資料
    #mongo --port 27018

    8. 查看資料庫
    rs1:SECONDARY>show databases

    此時會報錯
    Error: error: { "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 }

    原因在此處有詳細的說明
    請注意在預設的情況下,即使連結到 Secondary 節點也無法進行查詢的指令,必須透過 rs.slaveOk() 的指令才能宣告此一連線可用來進行查詢,此一設計的目的是為了避免程式誤連到 Secondary 後而不自知。因為 Secondary 節點與 Primary 節點內的資料存在一段的時間差,因此兩邊的資料可能不完全一致,這個現象對於某些應用來說將導致嚴重的不良後果,所以才需透過這種方式來確認程式的意圖。
    9. 執行slaveOk
     rs1:SECONDARY>rslaveOk()

    10. 此時就可以在Secondary執行與Primary相同的查詢

    如果查詢發現結果與Primary相同,表示資料可以成功的自動複製

    三、測試Sharding Cluster是否會正確切碎資料

    1. 下載免費資料集並解壓縮
    #wget http://jsonstudio.com/wp-content/uploads/2014/02/companies.zip
    #unzip companies.zip

    2. 導入資料到mongos(因為在sharding cluster中,mongos負責傳遞所有的請求)
    #mongoimport --host 192.168.1.4 --port 27018 --db shtest --collection companies --file companies.json

    3. 進入mongos並執行sh.status()
    #mongo --port 27018
    mongos>sh.status()
    可以看到顯示的信息有這樣的東西
      databases:
            {  "_id" : "shtest",  "primary" : "rs2",  "partitioned" : false }

    4. 讓shtest這個資料庫可以被切割
    mongos>sh.enableSharding("shtest")
    Enables sharding on the specified database. This does not automatically shard any collections but makes it possible to begin sharding collections using sh.shardCollection().
    透過官方解釋可以得知,這個指令並不會讓資料庫裡面的資料表被切割,透過這個指令只是允許透過sh.shardCollection()來讓資料表可以開始被切割

    5. 建立資料表索引
    mongos>db.companies.ensureIndex({_id:"hashed"})
    官方說明中寫道db.collection.ensureIndex()在3.0版後已經被較新的db.collection.createIndex()取代,但是使用較新的反而會無法切割成功,這點我還在研究

    6. 開始切割
    mongos>sh.shardCollection("shtest.companies", { "_id": "hashed" } )

    7. 確認碎片狀態
    mongos>sh.status()
    可以看到以下訊息
     shtest.companies
                            shard key: { "_id" : "hashed" }
                            unique: false
                            balancing: true
                            chunks:
                                    rs0     1
                                    rs1     1
                                    rs2     1
                            { "_id" : { "$minKey" : 1 } } -->> { "_id" : NumberLong("-591762798808544439") } on : rs0 Timestamp(2, 0)
                            { "_id" : NumberLong("-591762798808544439") } -->> { "_id" : NumberLong("7934911588406832349") } on : rs2 Timestamp(3, 0)
                            { "_id" : NumberLong("7934911588406832349") } -->> { "_id" : { "$maxKey" : 1 } } on : rs1 Timestamp(3, 1)
    可以看出每一個Replica Set都已經獲得了一份切片,同時還會告訴用戶哪部分的切片在哪裡


    伍、MongoDB相關指令


    執行mongod
    #mongod -f /etc/mongod.conf
    關閉 mongod
    #mongod -f /etc/mongod.conf --shutdown
    執行config server
    #mongod -f /etc/mongod-configserv.conf
    關閉config server
    #mongod -f /etc/mongod-configserv.conf --shutdown
    執行 mongos
    #mongos -f /etc/mongod-routingserv.conf
    關閉 mongos instance
    #killall mongos
    導入資料表
    #mongoimport --port port_number --db database_name --collection collection_name [--drop] --file file_name
    (使用--drop的話,如果資料庫中有名稱相同的collection,會先將舊的collection刪除,在導入新的collection)
    (導入CSV指定有點不同,可以去查閱官方文件)


    陸、Q&A

    問題一:

    執行sh.addShard()時出現類似的錯誤
    {        "ok" : 0,        "errmsg" : "in seed list rs0/192.168.1.1:27017,192.168.1.1:27018,192.168.1.1:27019, host 192.168.1.1:27017 does not belong to replica set rs0; found { hosts: [ \"com6:27017\", \"192.168.1.1:27018\", \"192.168.1.1:27019\" ], setName: \"rs0\", setVersion: 3, ismaster: true, secondary: false, primary: \"com6:27017\", me: \"com6:27017\", electionId: ObjectId('7fffffff0000000000000001'), maxBsonObjectSize: 16777216, maxMessageSizeBytes: 48000000, maxWriteBatchSize: 1000, localTime: new Date(1466274842539), maxWireVersion: 4, minWireVersion: 0, ok: 1.0 }",        "code" : 96}
    解決辦法:修改rs0的hostname

    1. 進入rs0的Primary並輸入rs.status(),檢查"members"的"name"
                    {                        "_id" : 0,                        "name" : "com6:27017",                        "health" : 1,                        "state" : 1,                        "stateStr" : "PRIMARY",                        "uptime" : 103335,                        "optime" : {                                "ts" : Timestamp(1466175445, 12359),                                "t" : NumberLong(1)                        },                        "optimeDate" : ISODate("2016-06-17T14:57:25Z"),                        "electionTime" : Timestamp(1466171888, 2),                        "electionDate" : ISODate("2016-06-17T13:58:08Z"),                        "configVersion" : 3,                        "self" : true                }
    如果是像這樣"name":"com6:27017",就要用rs.reconfig()修改"name"

    2. 執行以下指令修改"name"
    rs0:PRIMARY> cfg=rs.conf()
    rs0:PRIMARY> cfg.members[0].host="192.168.1.1:27017"
    rs0:PRIMARY> rs.reconfig(cfg)

    此時會回傳{ "ok" : 1 }表示修改成功,可以輸入rs.status()檢查成果

    此時sh.addShard()應該就可以正常執行

    問題二:執行sh.addShard()時出現類似的錯誤

    解決辦法一:檢查防火牆設定

    解決辦法二:在mongos所在的電腦中的/etc/hosts
    例如
    192.168.1.1 com6
    192.168.1.2 com7
    192.168.1.3 com8


    問題三:執行rs.initiate()時出現以下錯誤


    { "info2" : "no configuration explicitly specified -- making one", "me" : "0.0.0.0:27017", "errmsg" : "couldn't initiate : can't find self in the replset config", "ok" : 0}
    解決辦法:輸入以下指令
    >cfg = {"_id" : "rs0","members" : [{"_id" : 0,"host" : "192.168.1.1:27017"}]}
    (Primary的資料)
    >rs.initiate(cfg)

    柒、免費資料集


    1. https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json

    2. http://jsonstudio.com/wp-content/uploads/2014/02/companies.zip
    (14.8M compressed)

    3. http://jsonstudio.com/wp-content/uploads/2014/02/stocks.zip
    (1.6M compressed)

    4. http://jsonstudio.com/wp-content/uploads/2014/02/enron.zip
    (3.9M compressed)

    5. http://jsonstudio.com/wp-content/uploads/2014/02/zips.zip
    (656K compressed).

    6. http://jsonstudio.com/wp-content/uploads/2014/02/world_bank.zip

    (436K compressed)