一个大型,稳健,成熟的分布式系统背后,是由很多系统共同支撑的,我们将这些支撑系统成为分布式系统的基础设施。
持久化存储
简介
互联网领域常见的三种数据存储方式是 传统关系式数据库MySQL, Google提出的bigtable概念及其开源实现HBase,以及包含丰富数据类型的key-value存储Redis。
MySQL扩展
随着开源的IOE等商用存储解决方案的成本不断攀升,以MySQL等为代表的开源存储方案正成为互联网企业数据存储的首选方案。
业务拆分
一般业务发展初期,都是采用集中式设计,一块业务采用单库单表,整体采用单库多表的设计方式。但随着业务规模的发展,数据量将会越来越庞大,因此需要根据业务拆分。
某门户网站 根据新闻,用户,帖子,评论的拆分
复制策略
随着访问量的增加,拆分后某个库的压力越来越来越大,马上到达能力的瓶颈。因此解决这种读压力的方式,是采用复制策略,将一台MySQL数据库服务器的数据复制到其他MySQL服务器上,这样各台服务器拥有相同的数据,前端应用可以访问任意一台数据库服务器。
以一主一从架构方式,实现数据库的复制过程主要是Slave从Master获取binary log,然后本地镜像的执行日志中操作记录。由于复制过程是异步的,因此会存在一定的延迟现象。一主多从复制方式
M-Slaves架构方式存在的问题就是 单点故障,如果Master宕机,系统将无法写入,或者Master需要停机维护的时候也会影响到线上系统。为了尽量避免这样的情况,比较好的方式是采用 Dual-Master的架构。
所谓的 Dual Master 实际上就是两台MySQL服务器互相将对方作为自己的Master,自己作为Slave,这样任何一台服务器的数据变更,都会通过复制机制到另一台服务器。例如正常停机维护时,Master的切分操作如下:
- 停止当前Master的所有写入操作
- 在Master上设置只读操作,设置set global read_only = 1, 同时更新MySQL配置文件相应配置
- 在Master上设置 show Master status,记录Binary log
- 使用Master上的Binary log坐标,在stand by的Master上执行 select Master_pos_wait()等待 stand by的Binary log跟上Master的Binary log
- stand by Master 开启写入 设置read_only = 0
- 修改应用程序设置 进入新的Master( 原 stand by Master)
值得注意的是 当意外宕机的时候,需要将Binary log完全复制方能打开写入,否则会造成数据不一致的情况。
分库分表
随着业务规模的发展,很可能出现单表数据激增至千万甚至亿级,虽然能进M-S的数据库架构方式,当时对于Master的写入还是在单表上,因此需要对MySQL吞吐能力进一步扩展。对于大部分互联网公司数据都是和用户相关的,因此用户id是最常用的分表字段。
如图所示,通过对用户id进行取模,然后将得到分表后的访问表,如user_id = 257,257%256=1 将会进入order_1表。
面对海量数据的处理,除了分表策略,一定程度上也可以采用分库分表的方式。策略如下- 中间变量 = user_id%(库数量*每个库的表数量);
- 库=取整(中间变量/每个库表的数量)
- 表= 中间变量%每个库的表数量
加入原来的单表单库拆分成256个库 每个库包含1024张表,那么以user_id = 262145为例,路由计算为 - 中间变量= 262145 % (256*1024)= 1
- 库 = 取整(1/1024)= 0
- 表 = 1 % 1024 = 1
因此user_id = 262145的订单记录的查询和修改将会被路由到第0个库的第一张表进行执行。
虽然分库分表能带来数据存储能力的提升,但是会造成跨表的事物上升到分布式事务,而且难以进行多表关联查询,路由策略改变带来的扩容问题也比较麻烦。因此对于大数据量的查询和存储,除了MySQL的分库分表策略,还可以使用HBase来存储,优化查询。或者利用搜索引擎技术也能比较好的支持复制条件的组合查询,弥补数据库拆分带来的问题。具体学习,参见接下来的文章