如何基於MySQL及Redis搭建統一的KV存儲服務

本文介紹基於MySQL及Redis搭建統一的kv存儲服務:經常使用部署方式及其特色,Cluster manager,MySQL和Redis集羣方案,以及Sync數據同步服務。git

1、MySQL+Redis 經常使用部署方式

1.1 拓撲

1.2 特色

業務層經過雙寫同時寫MySQL及Redis。讀一般在Redis,若讀取不到,則從MySQL讀取,而後將數據同步到Redis,Redis一般設置expire或者默認LRU進行數據淘汰。github

這種使用方式會有以下問題:算法

1)MySQL及Redis存在數據不一致風險,尤爲是長時間運行的系統sql

2)業務層須要處理MySQL sql schema與Redis kv數據結構上的邏輯差別數據庫

3)無統一運維json

4)沒法方便擴容/縮容性能優化

2、KV 化的存儲使用理念

2.1 MySQL Is great NoSQL

參考文檔:服務器

http://www.aviransplace.com/2015/08/12/Mysql-is-a-great-nosql/微信

爲何要用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、將MySQL+Redis設計爲統一的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跨機分庫分表集羣

+ Redis集羣

+ MySQL->Redis實時數據同步服務

+ 統一的對外數據訪問接口

+ 內在的完整運維支持系統(支持在線擴容/縮容、failover等)

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、Cluster Manager服務

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-wechat/phxsql 金融級可靠性

5、 MySQL 集羣方案

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、Redis 集羣方案

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、 Sync 數據同步服務

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 其餘開源同步方案

1. tungsten-replicator(JAVA)

http://code.google.com/p/tungsten-replicator/

2. linkedin databus(JAVA)

https://github.com/linkedin/databus

3. Alibaba canal(JAVA)

https://github.com/alibaba/canal /

相關文章
相關標籤/搜索