是否采用读写分离方案

我们怎么决定,是采用读写分离的架构,还是采用sharding的架构?

               总体来讲,DBA团队prefer sharding机制,而不是严重依赖于replication based read/write split;
                对于现有的读写分离应用,要进行梳理;
                新的读写分离的方案,要么经过架构评审委员会评审,要么经过开发总监和DBA总监确认; 
               

读写分离的好处

  1. 在相对简单的付出下(只需要做读写分离,相对于sharding 而言,开发简单很多),可以解决系统的scalability的问题;
  2. 对于写的高可用相对要求低,对读的高可用要求/读的qps 要求非常高(比如用户登陆,移动的配置类型信息)可以很容易的实现系统扩展新问题
  3. 很容易实现读库的99.999%的高可用
  4. 可以某种程度上,降低大查询/报表类应用,对在线系统的压力;(比如wms/tms之类,不过不鼓励这种做法


读写分离的坏处:

  1. 应用开发需要清楚知道,什么时候读主库,什么时候读从库;如果主从延迟,导致异常单,应该作为bug处理;
  2. 对于应用开发,某种程度上,对开发的要求更高:不能写大job(从库一定delay),不能写大SQL(从库也很容易delay);
  3.  需要处理从库delay 的exception;何时回源主库;大部分是不能/不应该回源的;集中回源很容易压死主库;
  4. 容易让dev abuse系统;不做过多优化;
  5. 降低主库的写容量,当TPS超过6k,从库就会延迟逐步增加,而主库的TPS其实可以去到1.5w甚至2w

 

总体判断的guideline:

  1. 读写比率,必须在10:1 以上(建议20:1以上),才有可能考虑读写分离;不然原则上,不同意读写分离,不管如何还是要求避免延迟,比如:防止延迟的时候突发failover,那要么抛弃延迟的数据(如果硬件故障,大事务产生的大量binlog来不及传送,必然丢数据),要么等延迟过去拉长了故障恢复时间
  2. 读写分离的数据库,必须在读库前面,有LVS,来虚拟化读库的IP;原则上,10:1的读写分离,读库的压力会大大于写库;也需要多个数据库服务器来支撑;也需要LVS来掩盖和解决后端数据库服务器的维护问题(基本上读库可以逻辑上always online) 
  3.  读写分离的应用,程序要能够handle延迟的情况,必须能够容忍读库delay 3~5s; 如果不能容忍,请不要连接从库;
  4.  读写分离的主库,在系统设计支撑的容量,3年内,写库应该不需要sharding 拆分;不然,就是白白引入先读写分离,然后在主库sharding的复杂度;
  5. 读写分离的应用,不能因为读写分离了,就可以滥用系统;在主库的大事务,和在从库的大SQL,都会导致slave 的较大规模的delay; 
  6. 读写分离的应用,对于一个transaction里面的或者有强一致性依赖的,不能一下子去从库,一下子去主库;一个transaction 里面的信息,必须都是consistent的;属于ms级别的;主从复制必然有这个delay的;
  7. 原则上,读写分离的数据库,尽量不要让主库过于大(2个TB);
  8. 读写分离,不应该作为报表的标准解决方案;报表类型的应用(后端系统,比如vis, tps, ods, tms, wms等较多)原则上,应该考虑通过hadoop 来解决MySQL天然不适合报表类型的应用;在线系统和报表系统,天然应该分离;
  9. 读写分离应用: 对于cache侧有可能回源的应用, 可以考虑选择读写分离, 所有的读回源必须到 LVS vip

过去的例子,读写分离之后,由于应用设计的问题,带来的问题

  1. 订单/Coupon的问题;一个交易里面,一会儿读从库,一会儿读主库;在部分有几秒或者十几秒delay的场景下,发生异常;
    1. 订单例子
      业务场景:用户订单支付成功第三方支付平台回调流程中,pay域调用订单接口更新订单支付状态,主库更新成功从库同步存在延迟,pay域进一步调用审单接口进行审核(其中审核数据包含支付状态的判断),读取从库订单数据支付状态仍处于未支付状态,此时订单审单流程异常。
      1. 原始订单数据<order_sn,pay_status> = <15032483118418,0> (pay_status 0:未支付,1:支付成功)
      2. 订单支付成功后,订单主库数据<15032483118418,1> 从库数据<15032483118418,0>
      3. 审单时读取从库订单数据<15032483118418,0>,判断订单支付状态时出现异常
    2. coupon例子
      业务场景:coupon.api在大促前为了降低主库压力,在变更余额时判断余额金额的查询由主库迁到从库,并做了数据库主从一致性判断,当数据库主从不一致时,不能变更会员账户余额。但是订单退款其他操作是没有判断数据库主从一致性的,所以导致当退款操作时,数据库主从不同步时其他金额退款成功,礼品卡唯品卡账户退款是失败的。这段时间数据库主从一致性不稳定,导致出现异常单。

      解决方案:
      在订单退款的时候,礼品卡唯品卡账户从主库来获取。

 

 常见的slave delay的原因:

  1. 大job,一个update 几万条几十万条记录的;
  2. 一个update好多条记录(100+),而且是全表扫描类型的,没有合适的where 条件可以走索引的;因为我们是基于row的复制,每一条都要跑一边这个全表扫描/低效的索引扫描;这个问题在slave会放大;
  3. 表没有主键,导致从库复制每一条记录的DML都会做全表扫描
  4. slave 大SQL,比如频繁的大量的复杂join,耗尽磁盘的io能力或者耗光CPU资源;slave delay;
  5. DBA维护操作,比如大表的online DDL,或者dba 晚上的归档的job; --应该禁止;我们online ddl要求控制速度;归档也要控制速度和并发;麻烦的是两个同时kick off的时候;
  6. 网络或者系统问题;比如跨机房网络,同机房网络不稳定,系统不稳定(机器故障);
  7. MySQL bug; 
  8. 频繁对Text字段的表的读写,会把IO资源耗光,哪怕是flash卡
  9. 一些框架,查询也会发起事务,如set autocommit=0,又不关闭连接,到发布需要做ddl变更时,就会导致表锁延迟
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值