一. 應(yīng)用場(chǎng)景
redis 作為數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)引擎,有著很多優(yōu)點(diǎn)
- 高性能
單機(jī)引擎可以達(dá)到5-10W qps - 數(shù)據(jù)結(jié)構(gòu)全面,支持快速開發(fā)業(yè)務(wù)
string端三,list,set鹃彻,sorted set郊闯, hashes
問題:
- 存儲(chǔ)容量受限單機(jī)最大容量即為單機(jī)內(nèi)存最大容量
- 單機(jī)數(shù)據(jù)的持久化依賴aof和rdb機(jī)制,如果機(jī)器整個(gè)down掉蛛株,服務(wù)不可用
二. redis集群選型
正是由于單機(jī)redis引擎有著這樣的問題团赁,所以,基本每個(gè)互聯(lián)網(wǎng)公司都有自己的redis集群化方案谨履。
- 在redis客戶端lib中實(shí)現(xiàn)數(shù)據(jù)的分片并主從部署redis實(shí)例
優(yōu)點(diǎn):簡單然痊,性能損耗小
缺點(diǎn):擴(kuò)容方案復(fù)雜 - 集群化候選方案
1、NetFlix對(duì)Dynamo的開源通用實(shí)現(xiàn)Dynomite
Dynomite是NetFlix對(duì)亞馬遜分布式存儲(chǔ)引擎Dynamo的一個(gè)開源通用實(shí)現(xiàn)屉符,使用C/C++語言編寫剧浸、以代理的方式實(shí)現(xiàn)的Redis緩存集群方案。Dynomite不僅能夠?qū)⒒趦?nèi)存的Redis和Memcached打造成分布式數(shù)據(jù)庫矗钟,還支持持久化的MySQL唆香、BerkeleyDB、LevelDB等數(shù)據(jù)庫吨艇,并具有簡單躬它、高效、支持跨數(shù)據(jù)中心的數(shù)據(jù)復(fù)制等優(yōu)點(diǎn)东涡。Dynomite的最終目標(biāo)是提供數(shù)據(jù)庫存儲(chǔ)引擎不能提供的簡單冯吓、高效、跨數(shù)據(jù)中心的數(shù)據(jù)復(fù)制功能疮跑。Dynomite遵循Apache License 2.0開源協(xié)議發(fā)布组贺,更多關(guān)于Dynomite的信息請(qǐng)查看NetFlix技術(shù)博客對(duì)Dynomite的介紹。
2祖娘、Twitter的Redis/Memcached代理服務(wù)Twemproxy
Twemproxy是一個(gè)使用C語言編寫失尖、以代理的方式實(shí)現(xiàn)的、輕量級(jí)的Redis代理服務(wù)器,它通過引入一個(gè)代理層掀潮,將應(yīng)用程序后端的多臺(tái)Redis實(shí)例進(jìn)行統(tǒng)一管理菇夸,使應(yīng)用程序只需要在Twemproxy上進(jìn)行操作,而不用關(guān)心后面具體有多少個(gè)真實(shí)的Redis或Memcached實(shí)例仪吧,從而實(shí)現(xiàn)了基于Redis和Memcached的集群服務(wù)庄新。當(dāng)某個(gè)節(jié)點(diǎn)宕掉時(shí),Twemproxy可以自動(dòng)將它從集群中剔除薯鼠,而當(dāng)它恢復(fù)服務(wù)時(shí)摄咆,Twemproxy也會(huì)自動(dòng)連接。由于是代理人断,所以Twemproxy會(huì)有微小的性能損失。根據(jù) Redis作者的測(cè)試結(jié)果朝蜘,在大多數(shù)情況下恶迈,Twemproxy的性能相當(dāng)不錯(cuò),同直接操作Redis相比谱醇,最多只有20%的性能損失暇仲。Twemproxy遵循Apache License 2.0開源協(xié)議發(fā)布,更多關(guān)于Twemproxy的信息請(qǐng)登錄其在GitHub的主頁查看副渴。
3奈附、豌豆莢的 Redis 集群解決方案Codis
Codis是豌豆莢使用Go和C語言開發(fā)、以代理的方式實(shí)現(xiàn)的一個(gè)Redis分布式集群解決方案,且完全兼容Twemproxy煮剧。Twemproxy對(duì)于上一層的應(yīng)用來說, 連接Codis Proxy(Redis代理服務(wù))和連接原生的Redis服務(wù)器沒有明顯的區(qū)別,上一層應(yīng)用能夠像使用單機(jī)的 Redis一樣對(duì)待斥滤。Codis底層會(huì)處理請(qǐng)求的轉(zhuǎn)發(fā)、不停機(jī)的數(shù)據(jù)遷移等工作, 所有底層的一切處理, 對(duì)于客戶端來說是透明的勉盅∮悠模總之,可以簡單的認(rèn)為后臺(tái)連接的是一個(gè)內(nèi)存無限大的Redis服務(wù)草娜。Codis遵循MIT開源協(xié)議發(fā)布挑胸,更多關(guān)于Codis的信息請(qǐng)登錄其在GitHub的主頁查看。
另外宰闰,還有一些未開源的解決方案茬贵,比如新浪、百度移袍、淘寶解藻、騰訊等的Redis集群方案。在Redis官方正式推出可用于生產(chǎn)環(huán)境的集群方案前葡盗,以上三種方案是非常值得考慮在生產(chǎn)環(huán)境使用的方案舆逃。
三. 豌豆莢Codis
優(yōu)點(diǎn):
- codis-proxy基于GO和C語言,并發(fā)處理能力強(qiáng)勁
- 后端基于slot概念支持靈活,對(duì)用戶透明的擴(kuò)容和縮容操作路狮,甚至一鍵式auto rebalance
- 基于zookeeper提供了高可用的codis-proxy代理服務(wù)
- 集群管理工具豐富:頁面和命令行工具集虫啥,如:redis-port可以將老集群(redis單機(jī)或twemproxy集群)中數(shù)據(jù)方便的遷移導(dǎo)入至Codis
整體架構(gòu)
Codis 由四部分組成:
- Codis Proxy (codis-proxy)
codis-proxy 是客戶端連接的 Redis 代理服務(wù), codis-proxy 本身實(shí)現(xiàn)了 Redis 協(xié)議, 表現(xiàn)得和一個(gè)原生的 Redis 沒什么區(qū)別 (就像 Twemproxy), 對(duì)于一個(gè)業(yè)務(wù)來說, 可以部署多個(gè) codis-proxy, codis-proxy 本身是無狀態(tài)的. - Codis Manager (codis-config)
codis-config 是 Codis 的管理工具, 支持包括, 添加/刪除 Redis 節(jié)點(diǎn), 添加/刪除 Proxy 節(jié)點(diǎn), 發(fā)起數(shù)據(jù)遷移等操作. codis-config 本身還自帶了一個(gè) http server, 會(huì)啟動(dòng)一個(gè) dashboard, 用戶可以直接在瀏覽器上觀察 Codis 集群的運(yùn)行狀態(tài). - Codis Redis (codis-server)
codis-server 是 Codis 項(xiàng)目維護(hù)的一個(gè) Redis 分支, 基于 2.8.13 開發(fā), 加入了 slot 的支持和原子的數(shù)據(jù)遷移指令. Codis 上層的 codis-proxy 和 codis-config 只能和這個(gè)版本的 Redis 交互才能正常運(yùn)行. - ZooKeeper
Codis 依賴 ZooKeeper 來存放數(shù)據(jù)路由表和 codis-proxy 節(jié)點(diǎn)的元信息, codis-config 發(fā)起的命令都會(huì)通過 ZooKeeper 同步到各個(gè)存活的 codis-proxy.
如果希望有更簡單的訪問方式和更高的穩(wěn)定性:可以使用搭建HAProxy,但是會(huì)進(jìn)一步增加延遲奄妨。
安裝&管理集群
注意按照如下順序部署啟動(dòng)集群
- 啟動(dòng) dashboard *, 執(zhí)行 ../bin/codis-config dashboard, 該命令會(huì)啟動(dòng) dashboard *
- 初始化 slots , 執(zhí)行 ../bin/codis-config slot init涂籽,該命令會(huì)在zookeeper上創(chuàng)建slot相關(guān)信息
- 啟動(dòng) Codis Redis , 和官方的Redis Server參數(shù)一樣
- 添加 Redis Server Group , 每一個(gè) Server Group 作為一個(gè) Redis 服務(wù)器組存在, 只允許有一個(gè) master, 可以有多個(gè) slave, group id 僅支持大于等于1的整數(shù)
$ ../bin/codis-config server -h usage:
codis-config server list
codis-config server add <group_id> <redis_addr> <role>
codis-config server remove <group_id> <redis_addr>
codis-config server promote <group_id> <redis_addr>
codis-config server add-group <group_id>
codis-config server remove-group <group_id>
如: 添加兩個(gè) server group, 每個(gè) group 有兩個(gè) redis 實(shí)例,group的id分別為1和2砸抛, redis實(shí)例為一主一從评雌。
添加一個(gè)group,group的id為1直焙, 并添加一個(gè)redis master到該group
$ ../bin/codis-config server add 1 localhost:6379 master
添加一個(gè)redis slave到該group
$ ../bin/codis-config server add 1 localhost:6380 slave
類似的景东,再添加group,group的id為2
$ ../bin/codis-config server add 2 localhost:6479 master
$ ../bin/codis-config server add 2 localhost:6479 slave- 設(shè)置 server group 服務(wù)的 slot 范圍 Codis 采用 Pre-sharding 的技術(shù)來實(shí)現(xiàn)數(shù)據(jù)的分片, 默認(rèn)分成 1024 個(gè) slots (0-1023), 對(duì)于每個(gè)key來說, 通過以下公式確定所屬的 Slot Id : SlotId = crc32(key) % 1024 每一個(gè) slot 都會(huì)有一個(gè)特定的 server group id 來表示這個(gè) slot 的數(shù)據(jù)由哪個(gè) server group 來提供.
$ ../bin/codis-config slot -h
usage:
codis-config slot init
codis-config slot info <slot_id>
codis-config slot set <slot_id> <group_id> <status>
codis-config slot range-set <slot_from> <slot_to> <group_id> <status>
codis-config slot migrate <slot_from> <slot_to> <group_id> [--delay=<delay_time_in_ms>]
如:
設(shè)置編號(hào)為[0, 511]的 slot 由 server group 1 提供服務(wù), 編號(hào) [512, 1023] 的 slot 由 server group 2 提供服務(wù)
$ ../bin/codis-config slot range-set 0 511 1 online
$ ../bin/codis-config slot range-set 512 1023 2 online- 啟動(dòng) codis-proxy
../bin/codis-proxy -c config.ini -L ./log/proxy.log --cpu=8 --addr=0.0.0.0:19000 --http-addr=0.0.0.0:11000
剛啟動(dòng)的 codis-proxy 默認(rèn)是處于 offline狀態(tài)的, 然后設(shè)置 proxy 為 online 狀態(tài), 只有處于 online 狀態(tài)的 proxy 才會(huì)對(duì)外提供服務(wù)
../bin/codis-config -c config.ini proxy online <proxy_name> <---- proxy的id, 如 proxy_1- 打開瀏覽器 http://localhost:18087/admin
現(xiàn)在可以在瀏覽器里面完成各種操作了奔誓, 玩得開心
性能
8 core Xeon 2.10GHz, 多線程的 benchmark, 單 proxy 的 ops 是 12w. 而且 proxy 是可以動(dòng)態(tài)水平擴(kuò)展的, 理論上的性能瓶頸應(yīng)該是百萬級(jí)別的