本文介紹基於MySQL及Redis搭建統一的kv存儲服務:經常使用部署方式及其特色,Cluster manager,MySQL和Redis集羣方案,以及Sync數據同步服務。git
1.1 拓撲github
1.2 特色算法
業務層經過雙寫同時寫MySQL及Redis。讀一般在Redis,若讀取不到,則從MySQL讀取,而後將數據同步到Redis,Redis一般設置expire或者默認LRU進行數據淘汰。sql
這種使用方式會有以下問題:數據庫
1)MySQL及Redis存在數據不一致風險,尤爲是長時間運行的系統json
2)業務層須要處理MySQL sql schema與Redis kv數據結構上的邏輯差別性能優化
3)無統一運維服務器
4)沒法方便擴容/縮容、微信
2.1 MySQL Is great NoSQL數據結構
參考文檔:
http://www.aviransplace.com/2...
爲何要用MySQL:
「在可擴展系統構建時,一個很重要的考量是使用的技術是否成熟,選擇成熟的技術意味着出錯時可以迅速恢復。固然,開發者也能夠在項目中使用最新最牛的NoSQL數據庫,而這個數據庫在理論上也能夠良好地運行,然而在生產環境中出現了問題恢復須要多久?技術上已有的知識和經驗積累對於問題緩解相當重要,固然這個積累也包括了Google能夠搜索到的內容。
相比之下,關係型數據庫已經存在了超過四十年,業界對於關係型數據庫的維護也積累了大量的經驗。基於這些考慮,在新項目作技術選型時一般會選擇Mysql,而不是NoSQL數據庫,除非NoSQL真的有很是很是明顯的優點。」
2.2 KV理念
對於億級規模的數據存儲,尤爲是涉及到水平拆分跨機分庫分表的狀況下,線上對數據庫的訪問只能作的越簡單越好,group by/order by/分頁/通用join/事務等等的支持 在這個量級下的MySQL系統都是不合適的。
基本上目前全部的類proxy的MySQL方案真正上規模線上應用只能使用按拆分鍵進行讀寫操做,實際上也是一個用拆分鍵作的一個kv系統。
若想使用複雜的sql處理,最合理的部署方案是將Mysqlbinlog流水同步服務抽象出來,經過實時同步到OLAP類的系統進行處理。
因此面向海量存儲服務,MySQL從一開始就設計爲一個KV系統是可行的。value使用mediumblob存儲xml/json/protobuf/thrift格式化數據序列化以後的數據。
2.3 MySQL KV化的使用方式
一、用MySQL原來的主鍵或者索引鍵當作key
二、其餘全部的非主鍵非索引鍵,所有包裝到value裏面,value使用mediumblob存儲xml/json/protobuf/thrift格式化數據序列化以後的數據。
三、數據讀寫操做,均基於key一整行數據作讀寫,由業務層對裏面value的結構作解析及對內部結構作增刪改差,而不用變動 MySQL 自己的schema.
2.4 不適用場景
一、數據量和訪問量不大而且業務邏輯依賴 MySQL 數據庫進行處理的業務場景
二、涉及到多表join等的處理
對於此限制,也能夠經過將關聯表加工成基於關聯條件的一張寬表進行KV化。
三、涉及到事務等的處理。
3.1 目標
1)業務層經過統一方式訪問MySQL及Redis,再也不使用MySQL客戶端及Redis客戶端訪問
2)MySQL集羣化/Redis集羣化部署
3)將業務雙寫改成MySQL到Redis底層binlog數據同步方式完成同步
4)異構數據存儲支持最終一致性數據讀寫服務
5)支持存儲層面擴容縮容、failover且業務無感知
6)單機羣日百億次QPS/TPS支持(大類業務適度拆分到不一樣集羣中)
3.2 最終實現
基於MySQL+Redis的統一存儲服務(UniStore) =
MySQL跨機分庫分表集羣
3.3 架構圖
3.4 架構說明-將存儲設計爲一種服務
一、將MySQL+Redis作成統一KV存儲服務
二、經過acc proxy提供統一的數據訪問接口,經過統一協議支持跨語言數據訪問
訪問協議(自定義協議,protobuf協議,thrift協議等)
三、MySQL cluster支持跨機的分庫分表,schemaless設計,全部業務表KV化設計
四、Redis cluster支持跨機的實例拆分
五、Sync數據同步服務提供統一的Mysql到Redis 跨IDC/不跨IDC數據同步服務,小於100ms延時
六、整個系統不涉及到分佈式事務處理
3.5 三種部署方式
一、純MySQL集羣部署
此種部署方式等同於其餘MySQL proxy跨機分庫分表方案,讀寫均在MySQL
二、純Redis集羣部署
此種部署方式等同於其餘Redis proxy跨機分庫分表方案,讀寫均在Redis
三、MySQL+Redis異構部署
寫在MySQL,讀能夠從MySQL讀或者Redis讀,取決於業務對最新數據的讀取要求。
3.6 接口說明
一、int get(int appid, string key,string& value)
Redis讀操做專用
二、int get_with_version(int appid,string key, string& value, int64& version)
MySQL 讀操做專用,自帶版本號,防止寫覆蓋
三、int set(int appid, string key,string value, int64 version)
經過appid區分 MySQL 仍是Redis,均支持寫操做
四、int delete(int appid, string key)
經過appid區分 MySQL 仍是Redis, 不支持批量刪除
五、int multiget(int appid,vector<string> keys, map<string, string>& key_value_pairs)
支持批量讀操做,內部的數據路由及數據合併不用關心
六、intmultiset(int appid, map<string, string>& key_value_pairs)
不建議支持,涉及到跨機事務問題,沒法保證ACID
七、int Redis_op(string cmd, ……)
Redis其餘原生接口封裝(incr/expire/list/setnx等)
在此我向你們推薦一個架構學習交流羣。交流學習羣號:575745314 裏面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化、分佈式架構等這些成爲架構師必備的知識體系。還能領取免費的學習資源,目前受益良多
4.1 Cluster Manager 是一個service
cluster manager主要由以下幾種功能
1)MySQL/Redis分片路由信息的管理
一、 MySQL 分庫分表路由信息
二、Redis Slot路由信息
三、路由信息變動管理
2)Redis實例的探活及Redis擴容及縮容數據的遷移
好比連續3次,每次間隔30sRedis ping失敗,認爲實例掛掉,發出報警或者自動切換
3)Cluster manager不建議參與Mysql group主備層面的管理
MySQL 主備層面的集羣管理方案:
一、MHA+VIP (互聯網公司最經常使用)
二、微信phxsql系統:https://github.com/tencent-we... 金融級可靠性
5.1 架構圖
5.2 設計原則
1)統一的schemaless表結構
2)跨機的數據分佈
支持將單邏輯表水平拆分到多個Mysql服務器中
3)其餘說明
一、數據存儲可靠性高,全部業務數據經過序列化存儲到value列
二、每行數據自帶版本號,業務經過cas方式防止業務層多實例同時寫形成寫覆蓋
全局惟一版本號實現:本機微秒時間戳+server_id+proccess_id
三、固定百庫百表/百庫十表的數據拆分方式,多機跨Mysql實例部署
5.3 路由策略
1) 一致性hash
2) 路由計算算法
crc32/md5/基於字符串的各種hash算法
3) 路由信息格式
CREATETABLE Mysql_shard_info
(
appid
int(32) NOT NULL,
begin
int(32) NOT NULL,
end
int(32) NOT NULL,
ip
varchar(20) NOT NULL DEFAULT '',
port
int(11) NOT NULL DEFAULT '0',
user
varchar(50) NOT NULL DEFAULT '',
pwd
varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (appid
,begin
)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
5.4 數據遷移/自動擴展
數據遷移:
STEP1:利用 MySQL 主備複製機制進行數據複製
STEP2:數據差別小於某一臨界值,中止老分片寫操做(read-only)
STEP3:等待新分片數據更新完畢
STEP4:更路由規則路由規則,Cluster Manager向全部access proxy更新路由信息
STEP5:刪除老分片
自動擴展:
過程相似於數據遷移
6.1 部署方式
一、異構讀寫分離-MySQL寫,Redis讀
1) 數據寫操做在 MySQL ,讀操做在Redis
2) 數據經過Sync系統對binlog進行解析從Mysql同步到Redis
3) 數據有同步延遲(小於100ms),實現最終一致性
適用場景:要求數據高可靠,且讀量比較大,容許讀數據短期不一致,若指望一直讀到最新數據,請使用get_with_version()接口從 MySQL 讀取
二、獨立的Redis集羣服務
1)讀寫均在Redis,提供獨立的KV存儲服務
2) 用戶不用關注擴容/縮容/故障恢復等問題
3) 集羣內多業務混存,提升內存的使用率
適用場景:獨立的Redis集羣服務,相似twenproxy/codis
6.2 設計要點
一、一致性hash
支持數據跨Redis實例拆分,固定Slot數進行拆分
二、單機多實例部署
1)每一個物理機支持多Redis實例
2)每一個Redis實例只服務單個業務
3)Redis實例內存大小取決於業務需求,同時考慮業務訪問量和數據量
以RedisIP+port標示惟一實例,對於128G內存機器,
可配置3 Redis實例*每實例30G
或10 Redis實例*每實例10G
或20 Redis實例*每實例5G
拆分原則:單實例最大內存使用 < 本機剩餘內存
三、以Slot爲單位的平滑擴容/縮容
四、以Redis實例爲單位的failover處理
6.3 平滑擴容/縮容
主要步驟以下:
STEP1:確認擴容/縮容
Cluster manager經過對系統負載和數據量進行告警,進而確認進行擴容或者縮容
STEP2:修改路由表
1)修改路由表,將對應shard的狀態修改成migrate狀態,並將新路由推送到全部接入層
2)acc proxy會將寫操做轉到新的Redis實例中,讀操做默認先讀新Redis實例,key不存在會繼續從老的Redis實例中讀取
STEP3:數據遷移
1)Cluster manager經過自動數據遷移工具開始數據遷移,計劃依賴Redis的scan命令將相關的key掃出來,經過MIGRATE進行數據遷移
2)屢次掃描執行該過程,確認Slot中全部數據遷移完成
STEP4:修改路由表,遷移完成
Cluster manager將讀寫均切到新Redis實例,再也不從老Redis中進行操做
在此我向你們推薦一個架構學習交流羣。交流學習羣號:575745314 裏面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化、分佈式架構等這些成爲架構師必備的知識體系。還能領取免費的學習資源,目前受益良多
7.1 架構
7.2 應用場景
該服務徹底能夠抽象成獨立的數據同步分發服務,對於由於KV化而丟失的sql處理徹底能夠經過該服務同步到偏OLAP類的系統中進行處理。除了同步到Redis還能夠同步到ElasticSearch或者hbase或者寫hdfs文件基於hadoop生態去實現複雜計算和分析。
7.3 設計要點
一、集羣對集羣的實時數據同步
MySQL 統一要求binlog日誌爲row格式
二、不涉及DDL處理
因爲 MySQL schemaless的設計,不用考慮DDL處理,簡化同步服務(跨/不跨IDC)
三、基於時間戳的同步延遲監控
MySQL binlog row格式日誌自帶時間戳,基於此時間戳進行同步延遲監控
四、基於binlog文件名+offset的同步位置管理
定時定量持久化保存當前同步的binlog文件名及offset,用於各類場景下的同步恢復
五、基於行的並行同步
多線程同步模式,主線程經過對tableid或者key作hash,將binlogevent時間分發到對應worker線程的隊列中,worker線程依次從隊列中獲取binlog event執行
7.4 實現原理
原理相對比較簡單:
1)Sync同步工具模擬Mysql slave的交互協議,假裝本身爲 MySQL slave,向Mysqlmaster發送dump協議
2)Mysqlmaster收到dump請求,開始推送binary log給slave(也就是同步工具)
3)Sync同步工具解析binary log對象(原始爲byte流),並轉換成Redis或其餘存儲(hdfs/hbase/ES等數據庫)相應數據操做接口或者做爲消息存儲到MQ中(rocketmq或者kafka)
7.5 ROW 格式events
MySQL 5.5 Binlog的事件類型有多種,這裏只介紹與ROW模式相關的事件
1) QUERY_EVENT:與STATEMENT模式處理相同,存儲的是SQL,主要是一些與數據無關的操做,eg: begin、drop table
2) TABLE_MAP_EVENT:記錄了下一條事件所對應的表信息,在其中存儲了數據庫名和表名
3) WRITE_ROWS_EVENT:操做類型爲insert
4) UPDATE_ROWS_EVENT:操做類型爲update
5) DELETE_ROWS_EVENT:操做類型爲delete
6) XID_EVENT, 用於標識事務提交(commit)
典型的insert語句有以下4個events組成:
7.6 其餘開源同步方案
http://code.google.com/p/tung...
https://github.com/linkedin/d...