• MySQL分库分表


     MySQL分库分表 【转】http://blog.itpub.net/29254281/viewspace-1819422/
    MySQL处理大规模业务数据的方案一般都是分库分表.

    最开始一般都选择垂直拆分.
    比如电商网站,可能按照家电,图书,母婴等商品分类进行拆分.
    这样做的好处是拆分简单,并且没有破坏数据库事务.

    但是随着业务的增长,比如图书分类的订单数据表已经到达了10个T的规模.
    就需要考虑做水平拆分了.把逻辑上一个表的数据,分别存放到不同的数据库服务器.
    水平拆分的好处是
        多个数据库服务器分担CPU,内存,网络带宽的压力.
        多个数据库服务器分担备份、恢复的压力.
    缺点是
        破坏了原生的数据库事务.如果使用分布式事务,则会拖累数据库性能.
        增加了运维管理的负担.原来管一台服务器就行了,现在得管一堆服务器.

    水平拆分的三种主要方式
    1.Hash拆分.比如按照 userId mod 64.将数据分布在64个服务器上
    2.范围拆分.比如每台服务器计划存放一个亿的数据,先将数据写入服务器A.一旦服务器A写满,则将数据写入服务器B,以此类推.
    这种方式的好处是扩展方便.数据在各个服务器上分布均匀.
    3.路由表.自定义分布方式.
        

    吕海波老师SACC2015的内容.
    用事务补偿的方式,实现最终一致性.

    下图是水平拆分之后的结构. 假设用户A向B转账100元.



    由于水平拆分破坏了原有的事务.一个转账的业务,可能遇到如下的几个情况.


    第一种情况,应用写队列超时导致重发了消息.那么结果是A本来向B转账100元.结果却转账了200元..
    第二种情况,应用将消息成功写入队列,但是队列服务器挂了.结果是A向B转账失败.
    第三种情况,中间层(队列的消费者)将消息取出,修改A的账户余额,但是用户A的库挂了,导致事务失败.结果是A向B转账失败.
    第四种情况,中间层已经成功修改了用户A的账户余额,但是在修改B用户余额的时候,用户B的数据库挂了。结果是用户A的钱扣了,但是用户B的钱没有增加.
    第五种情况.中间层从队列拿到了消息,但是还未及处理,中间层本身挂了..

    最终一致性.
    1.应用先将本次事务的业务日志写入业务日志的数据库,暂不提交
    然后,向队列发送两个消息.一个消息是用户A -100元,另一个消息是用户B +100元.
    确保两个消息都成功入队,则提交业务日志的事务,获取全局事务ID(tran_id).一旦有任何异常,回滚事务.
    提交了事务,应用则可以直接返回.提示用户交易完成.


    2.中间层获取消息.先连接用户A的数据库.
    查询业务日志表(tran_log),如果没有该全局事务ID,则不予处理.(确认有这个全局事务,才处理)
    查询消息日志表(msg_log),如果存在记录,则不予处理.(防止消息超时重发)
    然后,开始事务.
    先update用户A,减100元.
    再写消息日志表,记录本次处理
    最后提交事务.


    3.中间层连接用户B的数据库,做相同的操作.

    每隔5分钟,检查tran_log和msg_log.如果有不一致的情况,则进行事务补偿.

    吕老师说到这里的时候,我觉得tran_log应该在如下的位置,然后作为各个底层库的Master.
    用MySQL异步复制,将tran_log复制到用户A、B所在的库.

    但是当面问吕老师,他说他们不是这么弄的.因为这个tran_log的数据量也是非常巨大.
    他们把tran_log放在了底层库,但是我实在想不出来这样怎么弄.
    可惜当时的环境也不容许我再刨根问底了.
    不过留着自己琢磨,也挺有意思.

    如果按照我的这个方式设计,后期问题会比较多,一个是tran_log数据量巨大.另外,tran_log所在的数据库容易产生瓶颈.

     
    参考文档 :
  • 相关阅读:
    python爬取京东菜单
    There is no Action mapped for namespace [/] and action name [] associated with context path [/ch_05_ActionAnnotation].
    Java基础学习,一些零散的笔记之抽象类与接口
    java基础学习,一些零散的笔记之内部类
    Java基础学习,一些零散的笔记之Java的包
    java native 关键字
    整理一下Java动态编译Java代码,并在加载到内存中然后执行类中方法的api的介绍
    有关jdbc驱动的问题,java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
    学习js,遇到坑爹的combobox的text值的清空问题
    怎样得到一个类中的所定义的变量的变量名
  • 原文地址:https://www.cnblogs.com/fangyuan303687320/p/5744346.html
Copyright © 2020-2023  润新知