此文已由作者张镐薪授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

基本概念

直接介绍概念太枯燥了,还是拿个和背景篇相似的例子介绍
业务场景:客户完成下单,快递员接受并更新运单状态,客户可以随时查看运单状态的任务。一票快递可能有多个子母件。同时,我们需要标记每个运单的状态,运单状态的解释和含义保存在运单状态字典表中。
因此,我们需要建立如下表:我们现在按照业务将数据库垂直拆分成运单库(单表2000tps,6000W数据),快递员库(单表1500tps,100W数据),客户库(单表1500tps,1000W数据记录);假设每个MySQL数据库单表不能超过2000W数据,单表不能超过1000tps。那么运单库则需要分成3片,客户库需要分成2片,统一由MyCat管理。如下图所示:

1.逻辑库

MyCat作为一个中间件,对应用应为无感知的。
应用访问MyCat,根据之前所述,应用感知到后台只是一个(或者多个,和访问MySQL实例一样)数据库(假设只有一个数据库,这个库叫SF,里面有运单相关表,快递员相关表和客户相关表);这里MyCat的数据库就是逻辑库。访问MyCat,结果应该如下面所示虽然其中的表可能存在于不同的库,但是表面上,他们属于同一个MyCat实例中的同一个逻辑库。所以,虽然上面的架构图显示他们不在同一个数据库,但是在MyCat中,他们在同一个逻辑库。

2.逻辑表

在逻辑库下的表就是逻辑表。逻辑表可以分片,也可以不分片。
orders表明显是要分片的表,但是在MyCat看来,他们虽然分布在不同的分片节点上(分布在不同的MySQL数据库上),但仍视为是同一个逻辑表,在同一个逻辑库里。

2.1分片表

分片表,是指那些原有的很大数据的表,需要切分到多个数据库的表,这样,每个分片都有一部分数据,所有分片构成了完整的数据。分片表都有自己的分片规则,根据分片规则确定分片。
配置里面,如下配置:

<table name="orders" primaryKey="id" dataNode="test$1-2" rule="mod-long"></table>

意思就是用mod-long规则根据主键id将运单表orders分割到test1,test2这两个数据库(分片节点)上。请求情况1:

select * from orders where id = 1;

对于分片表的查询,如果按照分片列查询,则请求只会被发送到一个分片上。请求情况2:

select * from orders where id < 100 and id > 0;

对于分片表的查询,如果按照分片列范围(在字段类型支持范围的情况下)查询,则请求会根据分片规则计算两个边界值,然后将请求发送到对应结果的分片上,并合并每个分片的结果。请求情况3:

select * from orders where initialpoint = 'Beijing';

像这种根据非分片列查询的情况,请求会被发送到所有分片上,并合并每个分片的结果。请求情况4:请求为更新类型的sql语句,与查询的三种情况相同处理。

2.2 非分片表

一个数据库中并不是所有的表都很大,某些表是可以不用进行切分的,非分片是相对分片表来说的,就是那些不需要进行数据切分的表。
例如:

<table name="courier" primaryKey="id" dataNode="test3"></table>

意思就是快递员表不用分片,保存在test3这个分片节点上。
对于非分片表的操作和对普通数据库的一样,因为不涉及到分布式数据库。

2.3 ER表

关系型数据库是基于实体关系模型(Entity-Relationship Model)之上,通过其描述了真实世界中事物与关系,Mycat中的ER表即是来源于此。根据这一思路,提出了基于E-R关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上,即子表依赖于父表,通过表分组(Table Group)保证数据Join不会跨库操作。
表分组(Table Group)是解决跨分片数据join的一种很好的思路,也是数据切分规划的重要一条规则。
如下:

<!-- 运单表,对主键id对2取模 --><table name="orders" primaryKey="id" dataNode="test$1-2" rule="mod-long">
    <!-- 运单子母件表,运单表的子表,order_id与orders的id列对应 -->
    <childTable name="orders_cargo" joinKey="order_id" parentKey="id">
    </childTable>        </table>

运单表为分片表,运单表和运单子母件表为一对多关系,可以做成父子表。
对于子表的sql请求,都是通过joinKey对应到父表对应字段后,按照之前分片表的规则进行处理。

2.4 全局表

一个真实的业务系统中,往往存在大量的类似字典表的表,这些表基本上很少变动,字典表具有以下几个特性:

  • 变动不频繁

  • 数据量总体变化不大

  • 数据规模不大,很少有超过数十万条记录。

对于这类的表,在分片的情况下,当业务表因为规模而进行分片以后,业务表与这些附属的字典表之间的关联,就成了比较棘手的问题,所以Mycat中通过数据冗余来解决这类表的join,即所有的分片都有一份数据的拷贝,所有将字典表或者符合字典表特性的一些表定义为全局表。
数据冗余是解决跨分片数据join的一种很好的思路,也是数据切分规划的另外一条重要规则
比如:

<!-- 运单状态信息表,公共表,放在和运单表同样的分片上 --><table name="order_status_interception" primaryKey="id" type="global" dataNode="test$1-2"></table>

运单状态信息字典表,只是注释每种运单状态,就是典型的字典表,与分片表orders为多对一的关系。
对于全局表,所有的查询请求,只会发送到其中一个全局表分片上执行,所有的更新请求,会在每个全局表分片上执行。

2.5 如何决定?

根据之前的描述,我们可以推断出,对于分片表的修改和查询,如果是按照分片字段进行查找的话,则请求会被转发到一个分片上。如果不是按照分片字段的话,就会把请求发到每一个分片上进行查找。所以,分片字段的选择比较重要!对于全局表,相当于在每个分片上有一份相同的复制,修改请求会在每一个分片上执行,但是查询只会落到一个分片上。所以,全局表尽量是不会改变的而且是需要和分片表做Join操作的,如果经常改变或者不需要做join,最好还是做成非分片表。

先抛出了这几种逻辑表的概念,大家先有个印象。现在我们结合具体实际讨论如何决定表的类型。

首先,orders表可定是分片表。orders_cargo表是子母件表,一个order可能有多个子母件,所以,最好把orders_cargo作为orders的子表。
这种情况下,orders与orders_cargo按照对应键(就是子表按照哪个键与主表的哪个键对应进行分片。比如orders_cargo就是order_id与orders的id对应。这是以order_id与orders的id进行join结果就是对的)join结果也是正确的。像这种简单的从属关系一对n的表,我们处理起来很简单,一般将它们按照需要做join的键设为父子表即可。

但是下面的场景很麻烦,比如快递员与运单就是多对多的关系,客户对于运单也是多对多的关系(一个收方,一个寄方)。我们既有快递员需要查看自己的所有运单的场景和客户查看自己所有运单的场景。相对的,我们也有查看一个运单涉及到的快递员还有客户的场景。
customer表(客户表)以及courier表(快递员表)因为与分片表orders之间不做join操作,所以不用作为公共表。
首先,关系表可以作为公共表,这样的话,涉及到与分片表的join操作没有限制,因为在每个分片,公共表都是完整的。但是,关系表的更新很频繁,我们可能不能忍受每更新一次关系表就跑到每个分片上都更新一次(性能,可靠性考虑)。
那么作为运单的子表呢?那么查找一个运单涉及到的快递员还有客户就比较简单。因为根据运单号(也就是分片id)查询,MyCat就会根据分片规则给他定位到具体分片,而不是去按分片搜索。

但是相应的,快递员查看自己所有运单的场景就比较慢,因为请求是发送到每一个分片上查找。作为快递员的子表也有同样的缺陷。
还有一种方法,就是这种关系表同时作为运单和快递员的子表。但是这样,目前需要应用自己去做双写。MyCat目前还没实现这种。当然,我觉得这是一个我们自己可以根据需要改进的地方。MyCat中间件根据关系冗余表关系进行双写

另外,究竟取哪种方法,都是从业务出发去考虑的。在这里,如果从快递员出发去查找以及从运单出发去查找的业务压力差不多大的话,那么最好就采用关系表同时作为运单和客户的子表这种方法。然后将快递员和运单的业务独立,每个业务应用都去维护自己的关系表,同时通过消息队列来保持关系表之间的一致性。这样也不失为一种方法。

免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击

相关文章:
【推荐】 大数据技术在金融行业的应用前景
【推荐】 寓教于乐——玩转角色互换游戏
【推荐】 巧用Scrum与Kanban

数据库路由中间件MyCat - 使用篇(1)的更多相关文章

  1. 数据库路由中间件MyCat - 背景篇(2)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. MyCat的前世今生 如前文所说,Amoeba.Cobar.MyCat等属于同宗一脉.若Amoeba能继续下 ...

  2. 数据库路由中间件MyCat - 源代码篇(13)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 4.配置模块 4.2 schema.xml 接上一篇,接下来载入每个schema的配置(也就是每个MyCat ...

  3. 数据库路由中间件MyCat - 使用篇(3)上篇

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 全局序列号 数据切分后,原有的关系数据库中的主键约束在分布式条件下将无法使用,因此需要引入外部机制保证数据唯 ...

  4. 数据库路由中间件MyCat - 源代码篇(7)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3. 连接模块 3.4 FrontendConnection前端连接 构造方法: public Fronte ...

  5. 数据库路由中间件MyCat - 源代码篇(15)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. public static void handle(String stmt, ServerConnectio ...

  6. 数据库路由中间件MyCat - 源代码篇(14)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 对于表的dataNode对应关系,有个特殊配置即类似dataNode="distributed(d ...

  7. 数据库路由中间件MyCat - 源代码篇(1)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 进入了源代码篇,我们先从整体入手,之后拿一个简单流程前端连接建立与认证作为例子,理清代码思路和设计模式.然后 ...

  8. 数据库路由中间件MyCat - 使用篇(4)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 配置MyCat 3. 配置conf/rule.xml 1.5GA版本中的规则配置比较笨,2.0中优化了一些, ...

  9. 数据库路由中间件MyCat - 使用篇(3)下篇

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 2. 配置conf/server.xml server.xml几乎保存了所有mycat需要的系统配置信息.其 ...

随机推荐

  1. H5如何做手机app(移动Web App)?图片轮播?ionic、MUI

    移动Web App 跨平台开发 用户不需要去卖场来下载安装App 任何时候都可以发布App只需要一个开发项目 可以使用HTML5,CSS3以及JavaScript以及服务器端语言来完成(PHP,Rub ...

  2. VC使用编译时间作为版本号

    常用方法分两步:1. 得到编译时间:2. 设置基准时间,以编译时间距基准时间的总天数的2倍作为版本号,适当情况还可加上初值: 其中第一步实现有两种方法: 1. 直接使用系统宏:CString OcxT ...

  3. js中(break,continue,return)的区别

    break 一般用于跳出整个循环(for,while) continue  跳出本次循环,进入下一次循环 return 只能出现在函数体内,一旦执行return,后面的代码将不会执行,经常用retur ...

  4. windows phone 8.0 的网络图片异步加载方案

    买了一本林政的8.1UI的书,看到一个使用弱引用对像来解决图片缓存的问题,刚好自已写的应用也遇到这个问题,于是小改动了一下代码,搬到了8.0版本来使用,代码由 zhxilin℃+ 大神提供了部分解决代 ...

  5. POJ 2104 K-th Number(分桶,线段树,主席树)

    一道比较经典的数据结构题.可以用多种方式来做. 一,分桶法(平方分解). 根据数字x的大小和区间内不大于x的数字数量cnt的单调性,可知第k大数kth对应的cnt应该满足cnt≥k, 且kth是满足条 ...

  6. Aizu 2300 Calender Colors(暴力)

    状压以后,直接暴力枚举,2^20约等于1e6,而且满足bitcount = m的状态很少. #include<bits/stdc++.h> using namespace std; +; ...

  7. java算法面试题:编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串,但要保证汉字不被截取半个, 如“我ABC”,4,应该截取“我AB”,输入“我ABC汉DEF”,6,应该输出“我ABC”,而不是“我ABC+汉的半个”。

    package com.swift; import java.util.Scanner; public class Hanzi_jiequ { public static void main(Stri ...

  8. Hotkeys.js 2.0.2 发布,JS 网页快捷键设置,捕获键盘输入和输入的组合键快捷键,它没有依赖

    这是一个强健的 Javascript 库用于捕获键盘输入和输入的组合键,它没有依赖,压缩只有只有(~3kb),gzip:1.9k. 更新内容: 添加测试用例: 添加更多特殊键支持: 修复bug. __ ...

  9. 洛谷P3374树状数组1

    下有彩蛋(from https://www.cnblogs.com/wuwangchuxin0924/p/5921130.html)树状数组的blog写的最好的是这位//https://www.cnb ...

  10. vue2.0:子组件调用父组件

    main.js文件添加如下: new Vue({ router, render: h => h(App), data: { eventHub: new Vue() }}).$mount('#ap ...