基於Redis的低成本高可用排行榜服務構建
引言
業務運營活動中排行榜的使用很廣泛,因此在三年前組內已經將排行榜服務元件化。整個服務是基於Redis的zset資料結構實現的。
限於當時Redis的發展,這套服務在高可用性方面有所欠缺。近年來,公司內外團隊在實現高可用Redis方面做了很多工作,也有很多部門提供現成的接入方案。但由於我們的Redis是定製過的(修改過原始碼),一方面是現有方案不支援接入,開源專案往往也需要修改原始碼進行適配,即便如此也不完全如意;另一方面我們自己也希望在升級迭代上能靈活掌控,所以權衡後還是決定自行部署和運維。
架構方案
早期的架構
在此之前,排行榜服務部署情況如下圖所示。此時,無狀態的接入層通過內部協議對外提供服務,各業務無需關注Redis的連線和呼叫方式。但是當redis master停止服務時,需要人工將slave提升為master,併發布配置將接入層的指向切換到slave。此方案雖然能在大多數情況下做到資料安全,但是在出現故障後人工介入之前,服務處於不可用狀態。
早期的架構
高可用架構
關於Redis的高可用部署方案,常見的有twemproxy、codis等,這些第三方方案往往需要引入額外元件,增加了運維成本。Redis本身提供了哨兵做HA,官方文件就哨兵的不同部署方案做了詳細介紹。本著低成本的原則,本文亦採用哨兵作高可用保障。改進的排行榜服務架構如下圖所示。
高可用架構
整個服務由以下部分組成:
排行榜CGI及業務模組:即服務使用方。排行榜CGI是一個通用化的供H5前端拉取排行榜資料的元件,業務無關。當業務有特殊邏輯時,亦可直接呼叫接入層介面。
服務接入層: 1. 對業務提供慣用的內部協議介面,供業務呼叫 2. 對單個原生命令無法完成的操作,如插入元素並返回排名操作,使用pipelining或lua優化查詢,細節對業務透明 3. 對業務隱藏從哨兵處獲取redis例項地址、master例項切換後地址更新等複雜邏輯 4. 當讀併發量較大時,可通過增加redis slave實現讀操作水平擴容,增加的slave可通過哨兵自動發現,對業務透明 5. 提供黑名單、週期榜單等業務通用能力支援
Redis例項:即Redis主從例項對。可以有多個slave以實現讀操作水平擴容。
哨兵叢集:提供高可用保證以及名服務。由3個哨兵組成,不與任何Redis例項混布。
監控與告警:藉助公司內部指標監控平臺實現指標監控以及異常告警。下一節詳述。
監控告警與自動運維
Redis存活監控與master自動切換。由哨兵負責。當例項程式終止或不可達時,哨兵會檢測到該例項的sdown
和odown
狀態(主觀下線與客觀下線),並在客觀下線後自動切換主例項。通過配置哨兵的notification-script
指令碼,在狀態變化時哨兵可以呼叫運維介面傳送簡訊和郵件通知。而配置reconfig-script
,能在新的master切換成功後觸發通知。
同時,接入層需要根據哨兵sentinel slaves
命令返回的資料自動發現slave,並根據狀態識別slave是否可用。幾種情況下的master和slave可用性如下表所示。
情形 | master狀態 | slave狀態 |
---|---|---|
master與slave正常 | 正常 | 正常。 |
master不可達 | 不可讀寫,等待恢復或切換 | 正常。 |
master切換後slave同步中 | 新master正常。 | 暫不可用。與新master成功建立連線前 |
新slave上線同步中 | 正常 | 暫不可用。與新master成功建立連線前 |
slave不可達 | 正常 | 不可讀。 |
Redis指標監控。在Redis例項機器上部署監控指令碼,通過crontab定時取樣,資料上報到監控平臺,方便檢視實時和歷史資料。監控的指標項可包含CPU使用率、記憶體使用率、key數量等,根據業務需要確定。
哨兵間相互監控。同樣由哨兵負責。但需要注意的是,當某個哨兵不可達時,其他哨兵只會觸發sdown
狀態變化,併傳送通知告警。
擴充套件能力
功能可擴充套件性。除了現有的黑名單、週期榜的能力,接入層還可以擴充套件豐富的業務功能,對業務遮蔽複雜的redis呼叫邏輯。比如,藉助LUA實現一個定時訊息佇列(參考此文)、介面流控等。
標準元件相容。接入層同時支援切換到其他符合Redis協議的元件,比如360 pika等。對於上層業務來說,不管是呼叫標準redis例項,還是其他元件,都沒有差別。
安裝包與配置管理
Redis安裝包與配置管理
業務的線上Redis使用相同的配置,統一使用內部服務包釋出系統管理Redis的安裝包和配置,以後臺server方式打包和部署。好處是:
便於版本管理,能跟蹤每一次變更情況。
跟蹤現網部署情況,可以看到部署了哪些例項,分別是哪個版本。當發現問題時可以方便評估受影響的範圍。
能將部署工作流程化。安裝包內包含了監控指令碼和工具,並且會自動新增指標監控的crontab。
哨兵安裝包與配置管理
業務同樣使用內部包釋出系統管理哨兵安裝包。但在配置管理方面與redis包有些不同,因為哨兵的配置檔案,同時也是哨兵的狀態儲存,故每個哨兵的線上配置是有差異的。我們將哨兵配置項區分為以下幾類:
分類 | 內容 | 特徵 |
---|---|---|
每例項獨有 | 哨兵ID | 配置變更後要保持不變,否則其他哨兵會認為有新哨兵加入且原哨兵不可用,將影響到故障恢復時多數派選舉leader過程。哨兵之所以不清除不可用的哨兵狀態,是為了防止當網路故障導致腦裂時錯誤的選舉區域性leader。 |
公共靜態配置 | 埠、工作目錄、日誌檔案等 | 每個例項一樣,且日常運維中無需變更。 |
公共動態配置 | 監控的Redis例項及紀元資訊。 | 這部分配置隨著監控例項的增刪會變化。值得注意的是,如果某個哨兵的紀元資訊被重置,其可以從別的哨兵處恢復。 |
故可以採用如下策略管理哨兵配置:
靜態配置放在
sentinel-base.conf
檔案中,隨哨兵安裝包釋出。指定配置檔案
sentinel.conf
啟動哨兵,首次部署啟動後會在配置sentinel.conf
中生成哨兵唯一idsentinel myid
,利用包部署服務等啟動後指令碼將其備份到myid.conf
中。指令碼如下:cd $install_path/conf grep -E '^sentinel myid' sentinel.conf > myid.conf最後利用配置系統下發例項監控配置檔案
sentinel.conf
,在配置檔案開頭用include方式包含sentinel-base.conf
和myid.conf
,且例項監控配置不需要包括epoch資訊。這樣,就能在每次下發新的配置後,保留哨兵ID和每個被監控例項的epoch資訊了。_不過需要注意的是,相比起使用配置中心動態儲存配置的方式,當線上故障導致master變更後,需要手動修改配置。_include "/usr/local/services/redis_sentinel_qzmall-1.0/conf/sentinel-base.conf" include "/usr/local/services/redis_sentinel_qzmall-1.0/conf/myid.conf"
# 例項1
sentinel monitor my_redis 100.66.82.X 6479 2
sentinel down-after-milliseconds my_redis 10000
sentinel auth-pass my_redis mypasswd
sentinel parallel-syncs my_redis 1
sentinel notification-script my_redis /usr/local/services/redis_sentinel_qzmall-1.0/bin/notification-script.sh
sentinel client-reconfig-script my_redis /usr/local/services/redis_sentinel_qzmall-1.0/bin/reconfig-script.sh
結語
與大多數公共組建一樣,本文的Redis部署方案也由接入層、哨兵(名服務)、Redis例項(核心服務)、監控服務等部分組成。除哨兵與Redis是官方開源元件外,其他部分均選擇公司已有技術和運維平臺完成。方案整體既能滿足日常業務需求,也能滿足日常運維與監控要求,在可用性與維護成本上取得了一個平衡。
相關文章
- 用 Hystrix 構建高可用服務架構架構
- 【Redis】基於consul的Redis高可用方案Redis
- Redis系列(四)-低成本高可用方案設計Redis
- 構建基於RocketMQ的分散式事務服務MQ分散式
- 基於Redis構建微服務的反應式架構 - bitsrcRedis微服務架構
- 關於服務高可用的一些理解
- 基於 Apache ShardingSphere 構建高可用分散式資料庫Apache分散式資料庫
- 【Redis】Sentinel 高可用架構Redis架構
- Redis Sentinel高可用架構Redis架構
- LVS + Keepalived + Nginx基於DR模式構建高可用方案Nginx模式
- 基於 ASK + EB 構建容器事件驅動服務事件
- 高可用服務之Keepalived基礎入門
- 如何用3臺機器輕鬆搭建一個高可用Redis服務架構?Redis架構
- 基於ubuntu映象構建redis映象UbuntuRedis
- 會員服務在高可用架構的實戰探索架構
- Redis服務之高可用元件sentinelRedis元件
- 使用 TiKV 構建分散式類 Redis 服務分散式Redis
- 基於MFS高可用的分散式儲存架構分散式架構
- 基於 MHA 高可用的 MySQLMySql
- WEB叢集- 高可用服務Web
- Kubernetes-基於Helm安裝部署高可用的RedisRedis
- 遊戲服務端的高併發和高可用遊戲服務端
- 構建ORACLE高可用環境Oracle
- Redis 高可用架構最佳實踐Redis架構
- 高可用架構之高可用的應用和服務架構
- OpenStack的高可用系統構建(1)
- OpenStack的高可用系統構建(2)
- 基於pacemaker 的高可用叢集架構----1 基礎介紹架構
- 使用 Docker Compose 本地部署基於 Sentinel 的高可用 Redis 叢集DockerRedis
- 工商銀行基於 Dubbo 構建金融微服務架構的實踐-服務發現篇微服務架構
- spring cloud構建網際網路分散式微服務雲平臺-高可用的服務註冊中心SpringCloud分散式微服務
- Keepalived實現服務高可用
- go基於grpc構建微服務框架-服務註冊與發現GoRPC微服務框架
- 如何基於 Redis 構建應用程式元件Redis元件
- 關於Redis的幾件小事 | 高併發和高可用Redis
- Redis高可用之戰:主從架構Redis架構
- 同程旅行基於 RocketMQ 高可用架構實踐MQ架構
- golang實現基於redis和consul的可水平擴充套件的排行榜服務範例GolangRedis套件