如何基于MySQL及Redis搭建统一的KV存储服务

本文介绍基于MySQL及Redis搭建统一的kv存储服务:经常使用部署方式及其特色,Cluster manager,MySQL和Redis集群方案,以及Sync数据同步服务。git

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

1.1 拓扑github

clipboard.png

1.2 特色算法

业务层经过双写同时写MySQL及Redis。读一般在Redis,若读取不到,则从MySQL读取,而后将数据同步到Redis,Redis一般设置expire或者默认LRU进行数据淘汰。sql

这种使用方式会有以下问题:数据库

1)MySQL及Redis存在数据不一致风险,尤为是长时间运行的系统json

2)业务层须要处理MySQL sql schema与Redis kv数据结构上的逻辑差别性能优化

3)无统一运维服务器

4)没法方便扩容/缩容、微信

2、KV 化的存储使用理念

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、将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 架构图

clipboard.png

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-we... 金融级可靠性

5、 MySQL 集群方案

5.1 架构图

clipboard.png

5.2 设计原则

1)统一的schemaless表结构

clipboard.png

2)跨机的数据分布

支持将单逻辑表水平拆分到多个Mysql服务器中

3)其余说明

一、数据存储可靠性高,全部业务数据经过序列化存储到value列

二、每行数据自带版本号,业务经过cas方式防止业务层多实例同时写形成写覆盖

全局惟一版本号实现:本机微秒时间戳+server_id+proccess_id

三、固定百库百表/百库十表的数据拆分方式,多机跨Mysql实例部署

5.3 路由策略

1) 一致性hash

clipboard.png

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:删除老分片

自动扩展:

过程相似于数据迁移

clipboard.png

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 架构

clipboard.png

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 实现原理

clipboard.png

原理相对比较简单:

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组成:

clipboard.png

7.6 其余开源同步方案

  1. tungsten-replicator(JAVA)

http://code.google.com/p/tung...

  1. linkedin databus(JAVA)

https://github.com/linkedin/d...

  1. Alibaba canal(JAVA)

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

相关文章
相关标签/搜索