近幾年,隨著網際網路的飛速發展,作為程式設計師,我們需要處理的資料規模也在不斷擴大。如果你使用Redis作為資料庫時,面臨大資料高併發的場景時,單個Redis例項就會顯得力不從心。這時Redis的叢集方案應運而生,他將眾多Redis例項綜合起來,共同應對大資料高併發的場景。
Codis是Redis叢集方案的一種。它是由豌豆莢的中介軟體團隊開發的,所以,它有一套詳細的中文版README,方便大家學習。
它的架構如上圖所示,由codis-proxy對外提供Redis的服務。ZooKeeper用來儲存資料路由表和codis-proxy節點的元資訊。codis-proxy會監聽所有的redis叢集,當Redis叢集處理能力達到上限時,可以動態增加Redis例項來實現擴容的需求。
元件介紹
- Codis Proxy:像剛才所說的,它對外提供Redis服務,除了一些不支援的命令外(不支援的命令列表),表現的和原生的Redis沒有區別。由於它是無狀態的,所以我們可以部署多個節點,從而保證了可用性。
- Codis Dashboard:叢集管理工具,支援Codis Proxy的新增刪除以及資料遷移等操作。對於一個Codis叢集,Dashboard最多部署一個
- Codis Admin:叢集管理的命令列工具
- Codis FE:叢集管理介面,多個Codis叢集可以共用一個Codis FE,通過配置檔案管理後端的codis-dashboard
- Storage:為叢集提供外部儲存,目前支援ZooKeeper、Etcd、Fs三種。
- Codis Server:基於3.2.8分支開發,增加額外的資料結構,用來支援slot有關的操作及資料遷移指令。
Codis分片原理
現在我們已經知道了Codis會將指定key的Redis命令轉發給下層的Redis。那麼Codis如何知道某個key在哪個Redis上呢。
Codis採用Pre-sharding的技術來實現資料分片,預設分為1024個slot(0-1023)。Codis在接收到命令時,先對key進行crc32運算,然後再對1024取餘,得到的結果就是對應的slot。然後就可以將命令轉發給slot對應的Redis例項進行處理了。
擴容操作
Codis的動態擴容/縮容能力是它的一大亮點之一。它可以對Redis客戶端透明。在擴容時,Codis提供了SLOTSSCAN指令,這個指令可以掃描指定的slot上的所有key,然後對每個key進行遷移。在擴容過程中,如果有新的key需要轉發到正在遷移的slot上,那麼codis會判斷這個key是否需要遷移,如果需要,則對指定的key進行強制遷移,遷移完成後,再將命令轉發到新的Redis上。
看了上面的介紹是不是覺得擴容是一件很麻煩的事情,Codis已經為我們考慮到這點了,它提供了自動均衡的功能,只需要在介面上點一下"Auto Rebalance"按鈕,就可以自動實現slot遷移(可以說非常貼心了)。縮容也比較簡單,只需要將需要下線的例項的slot遷移到其他例項上,然後刪除group就可以了。
Codis的缺點
當Redis Group的master掛掉時,codis不會自動將某個slave升為master,codis提供了一個叫做codis-ha的工具,這個工具通過dashboard提供RESTful API來實現自動主從切換。但是,當codis將某個slave升為master時,其他的slave並不會改變狀態,仍然會從舊的master上同步資料,這就導致了主從資料不一致。因此,當出現主從切換時,需要管理員手動建立新的sync action來完成資料同步。
此外,Codis還面臨一個比較尷尬的情況就是,由於它不是Redis“親生”的,因此,當Redis釋出了new feature時,它總會慢一步,因此,它需要在Redis釋出new feature後迅速趕上,以保持競爭力。
搭建Codis
- 安裝Go執行環境
Mac使用者可以參考這個,其他系統的使用者也可以看這個教程。
安裝好以後,驗證一下是否安裝成功
$ go version
go version go1.11.2 darwin/amd64
複製程式碼
- 下載Codis原始碼
需要下載到指定目錄:$GOPATH/src/github.com/CodisLabs/codis
$ mkdir -p $GOPATH/src/github.com/CodisLabs
$ cd $_ && git clone https://github.com/CodisLabs/codis.git -b release3.2
複製程式碼
- 編譯原始碼
進入原始碼的codis目錄,直接執行make命令即可。編譯完成後,bin目錄下的結構應該是這樣的
$ ll bin
total 178584
drwxr-xr-x 8 jackey staff 256B 11 13 10:57 assets
-rwxr-xr-x 1 jackey staff 17M 11 13 10:57 codis-admin
-rwxr-xr-x 1 jackey staff 18M 11 13 10:56 codis-dashboard
-rw-r--r-- 1 jackey staff 5B 11 21 18:06 codis-dashboard.pid
-rwxr-xr-x 1 jackey staff 16M 11 13 10:57 codis-fe
-rw-r--r-- 1 jackey staff 5B 11 21 18:24 codis-fe.pid
-rwxr-xr-x 1 jackey staff 15M 11 13 10:57 codis-ha
-rwxr-xr-x 1 jackey staff 19M 11 13 10:57 codis-proxy
-rw-r--r-- 1 jackey staff 5B 11 21 18:08 codis-proxy.pid
-rwxr-xr-x 1 jackey staff 1.1M 11 13 10:56 codis-server
-rwxr-xr-x 1 jackey staff 98K 11 13 10:56 redis-benchmark
-rwxr-xr-x 1 jackey staff 161K 11 13 10:56 redis-cli
-rwxr-xr-x 1 jackey staff 1.1M 11 13 10:56 redis-sentinel
-rw-r--r-- 1 jackey staff 170B 11 13 10:56 version
複製程式碼
到這裡為止,我們的準備工作已經完成了。接下來我們來看一下如何在單機環境啟動測試叢集。
- 啟動codis-dashboard
進入admin目錄,執行codis-dashboard-admin.sh指令碼
$ ./codis-dashboard-admin.sh start
/Users/jackey/Documents/go_workspace/src/github.com/CodisLabs/codis/admin/../config/dashboard.toml
starting codis-dashboard ...
複製程式碼
然後檢視日誌,觀察是否啟動成功
$ tail -100 ../log/codis-dashboard.log.2018-11-21
2018/11/21 18:06:57 main.go:155: [WARN] option --pidfile = /Users/jackey/Documents/go_workspace/src/github.com/CodisLabs/codis/bin/codis-dashboard.pid
2018/11/21 18:06:57 topom.go:429: [WARN] admin start service on [::]:18080
2018/11/21 18:06:57 fsclient.go:195: [INFO] fsclient - create /codis3/codis-demo/topom OK
2018/11/21 18:06:58 topom_sentinel.go:169: [WARN] rewatch sentinels = []
2018/11/21 18:06:58 main.go:179: [WARN] [0xc000374120] dashboard is working ...
複製程式碼
- 啟動codes-proxy
執行codis-proxy-admin.sh指令碼
$ ./codis-proxy-admin.sh start
/Users/jackey/Documents/go_workspace/src/github.com/CodisLabs/codis/admin/../config/proxy.toml
starting codis-proxy ...
複製程式碼
檢視是否啟動成功
$ tail -100 ../log/codis-proxy.log.2018-11-21
2018/11/21 18:08:34 proxy_api.go:44: [WARN] [0xc0003262c0] API call /api/proxy/start/212d13827c84455d487036d4bb07ce15 from 10.1.201.43:58800 []
2018/11/21 18:08:34 proxy_api.go:44: [WARN] [0xc0003262c0] API call /api/proxy/sentinels/212d13827c84455d487036d4bb07ce15 from 10.1.201.43:58800 []
2018/11/21 18:08:34 proxy.go:293: [WARN] [0xc0003262c0] set sentinels = []
2018/11/21 18:08:34 main.go:343: [WARN] rpc online proxy seems OK
2018/11/21 18:08:35 main.go:233: [WARN] [0xc0003262c0] proxy is working ...
複製程式碼
- 啟動codis-server
執行codis-server-admin.sh指令碼
$ ./codis-server-admin.sh start
/Users/jackey/Documents/go_workspace/src/github.com/CodisLabs/codis/admin/../config/redis.conf
starting codis-server ...
複製程式碼
檢視是否啟動成功
$ tail -100 /tmp/redis_6379.log
12854:M 21 Nov 18:09:29.172 * Increased maximum number of open files to 10032 (it was originally set to 256).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.11 (de1ad026/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 12854
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
12854:M 21 Nov 18:09:29.187 # Server started, Redis version 3.2.11
12854:M 21 Nov 18:09:29.187 * The server is now ready to accept connections on port 6379
複製程式碼
如果執行報錯,請先確認使用的使用者是否有/tmp/redis_6379.log檔案的讀寫許可權。
這裡我為了測試Codis的Auto Rebalance功能,所以啟動了兩個例項。方法很簡單,只需要分別將admin/codis-server-admin.sh和config/redis.conf這兩個檔案複製一份,修改檔案中的埠等資訊,然後再以同樣的方法執行一下新的指令碼。
- 啟動codis-fe
執行codis-fe-admin.sh指令碼
$ ./codis-fe-admin.sh start
starting codis-fe ...
複製程式碼
檢視是否執行成功
$ tail -100 ../log/codis-fe.log.2018-11-21
2018/11/21 18:24:33 main.go:101: [WARN] set ncpu = 4
2018/11/21 18:24:33 main.go:104: [WARN] set listen = 0.0.0.0:9090
2018/11/21 18:24:33 main.go:120: [WARN] set assets = /Users/jackey/Documents/go_workspace/src/github.com/CodisLabs/codis/bin/assets
2018/11/21 18:24:33 main.go:162: [WARN] set --filesystem = /tmp/codis
2018/11/21 18:24:33 main.go:216: [WARN] option --pidfile = /Users/jackey/Documents/go_workspace/src/github.com/CodisLabs/codis/bin/codis-fe.pid
複製程式碼
全部啟動成功之後,就可以訪問http://127.0.0.1:9090,開始設定叢集了。
- 新增group
剛剛我們啟動了兩個codis-server,因此,我們可以new兩個group,然後分別將codis-server加入到兩個group中
- 初始化slot
一開始所有的slot都是offline狀態。
點選下方的Rebalance All Slots按鈕,codis會自動把1024個slot分配給兩個group(每個分512個)。
當然,也可以手動分配slot,比如,我們將group-1的10個slot分配給group-2,只需要點選Migrate Some按鈕即可。
小結
Codis的動態擴容能力簡直好用到爆 ,不過目前也存在一些問題(前面我們也介紹過了)。所以你的叢集是否要使用Codis還需要看具體的需求。最後還是要為Codis的開發團隊點贊,另外他們還開發出了一套分散式資料庫——TiDB。有興趣的同學可以學習一下。