近幾年,隨着互聯網的飛速發展,做爲程序員,咱們須要處理的數據規模也在不斷擴大。若是你使用Redis做爲數據庫時,面臨大數據高併發的場景時,單個Redis實例就會顯得力不從心。這時Redis的集羣方案應運而生,他將衆多Redis實例綜合起來,共同應對大數據高併發的場景。html
Codis是Redis集羣方案的一種。它是由豌豆莢的中間件團隊開發的,因此,它有一套詳細的中文版README,方便你們學習。git
它的架構如上圖所示,由codis-proxy對外提供Redis的服務。ZooKeeper用來存儲數據路由表和codis-proxy節點的元信息。codis-proxy會監聽全部的redis集羣,當Redis集羣處理能力達到上限時,能夠動態增長Redis實例來實現擴容的需求。程序員
如今咱們已經知道了Codis會將指定key的Redis命令轉發給下層的Redis。那麼Codis如何知道某個key在哪一個Redis上呢。github
Codis採用Pre-sharding的技術來實現數據分片,默認分爲1024個slot(0-1023)。Codis在接收到命令時,先對key進行crc32運算,而後再對1024取餘,獲得的結果就是對應的slot。而後就能夠將命令轉發給slot對應的Redis實例進行處理了。redis
Codis的動態擴容/縮容能力是它的一大亮點之一。它能夠對Redis客戶端透明。在擴容時,Codis提供了SLOTSSCAN指令,這個指令能夠掃描指定的slot上的全部key,而後對每一個key進行遷移。在擴容過程當中,若是有新的key須要轉發到正在遷移的slot上,那麼codis會判斷這個key是否須要遷移,若是須要,則對指定的key進行強制遷移,遷移完成後,再將命令轉發到新的Redis上。數據庫
看了上面的介紹是否是以爲擴容是一件很麻煩的事情,Codis已經爲咱們考慮到這點了,它提供了自動均衡的功能,只須要在界面上點一下"Auto Rebalance"按鈕,就能夠自動實現slot遷移(能夠說很是貼心了)。縮容也比較簡單,只須要將須要下線的實例的slot遷移到其餘實例上,而後刪除group就能夠了。後端
當Redis Group的master掛掉時,codis不會自動將某個slave升爲master,codis提供了一個叫作codis-ha的工具,這個工具經過dashboard提供RESTful API來實現自動主從切換。可是,當codis將某個slave升爲master時,其餘的slave並不會改變狀態,仍然會從舊的master上同步數據,這就致使了主從數據不一致。所以,當出現主從切換時,須要管理員手動建立新的sync action來完成數據同步。api
此外,Codis還面臨一個比較尷尬的狀況就是,因爲它不是Redis「親生」的,所以,當Redis發佈了new feature時,它總會慢一步,所以,它須要在Redis發佈new feature後迅速遇上,以保持競爭力。bash
Mac用戶能夠參考這個,其餘系統的用戶也能夠看這個教程。數據結構
安裝好之後,驗證一下是否安裝成功
$ go version
go version go1.11.2 darwin/amd64
複製代碼
須要下載到指定目錄:$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
複製代碼
到這裏爲止,咱們的準備工做已經完成了。接下來咱們來看一下如何在單機環境啓動測試集羣。
進入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 ...
複製代碼
執行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-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-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,開始設置集羣了。
剛剛咱們啓動了兩個codis-server,所以,咱們能夠new兩個group,而後分別將codis-server加入到兩個group中
一開始全部的slot都是offline狀態。
點擊下方的Rebalance All Slots按鈕,codis會自動把1024個slot分配給兩個group(每一個分512個)。
固然,也能夠手動分配slot,好比,咱們將group-1的10個slot分配給group-2,只須要點擊Migrate Some按鈕便可。
Codis的動態擴容能力簡直好用到爆 ,不過目前也存在一些問題(前面咱們也介紹過了)。因此你的集羣是否要使用Codis還須要看具體的需求。最後仍是要爲Codis的開發團隊點贊,另外他們還開發出了一套分佈式數據庫——TiDB。有興趣的同窗能夠學習一下。