从根上理解高并发之数据库

       想必在我们开发一个新项目或者一个新产品时候,都会遇到一个问题就是时间紧,任务重。为什么这么紧呢?有些可能是因为公司就是想着快速试错快速找准方向,有些可能就是非常迫切需要这么一个系统,当然也还有一些其他情况哈,就不多举例了。在如此紧迫的环境下,时间光开发功能测试都不够,哪还有时间考虑整体系统架构,所以这个时候基本研发和leader也都达成一致,先上线后期再迭代优化。

图片

       这个时候基本就是单数据库的模式,什么是单数据库呢就是线上只有一个数据库,而且供多个数据库用户使用,这个模式往往是数据量不是很大。只需要满足基础的查询和写入操作就可,相对来说运维成本也很低。

图片

       但是随着使用用户增多,数据量增大,查询需求变的越来越多。这个时候整体架构可以优化为用户查询请求先经过redis缓存,如果有直接从缓存中拿去数据返回,如果缓存中没有后再到数据库查询数据,查到数据后再缓存到redis中同时返回给用户。这种模式极大缓解的数据库的查询压力,但是这种模式也是极其危险的,因为一旦数据库挂掉,意味着你整个服务写能力将会不可用,读能力也会受到很大影响。尤其是这个阶段有一定的用户基础,一旦发生故障将是灾难性的影响。

图片

       不慌,我们能想到的问题,早有先人给我们想好了,拿mysql来说,mysql支持一主多从架构。什么是一主多从呢,其实就是一个master机器,多个slave机器,master机器负责写入数据,同步数据给slave机器,也就是说slave机器和master机器将时刻保持数据同步,此时如果master查询压力过大我们可以把查询请求分配到slave机器上,分担master压力,提高并发处理能力。而且这种模式如果master机器挂掉后,运维可以手动操作让slave机器变为master机器继续提供服务,防止数据丢失和整个系统崩溃。那么我们现在已经是一主多从的稳定性架构那我们是不是就可以一劳永逸了呢,答案很明显是否定的,因为此种架构解决了查询压力大的问题,但是没有解决写入压力,写入还是集中在一个机器上,随着数据越来越多,单机写入会越来越不堪重负。

图片

       那我们如何优化写入压力呢,这个可以从我们生活的一个例子举起。大家旅游的时候一定去过很多乡村,乡村公路大部分都是单车道,好一点的可能就是双车道,为什么它不搞成多车道呢?因为车少啊,那为啥省道和国道都是双向六车道、八车道,因为车多呀,哈哈哈。不好意思,有点跑偏了,我们的重点是学习这种思路,既然一个车道承载不了这么多车,那我们就多开几个呗。哎,你开窍了,数据库也是同理,一个写入压力大你就写入两个呗,两个不行就三个呗,分散承受,单个压力不就小了吗,假设一个数据库节点可以扛住5000并发,十个就5w并发,一百个就50w,天呐,想想就刺激。其实这种思路就是著名的分片思想。业界也有很多分片的中间件,比如说阿里的mycat、当当的sharding-jdbc、360的Atlas、小米的gaea等,感兴趣的小伙伴可以去了解下。空有思想但是我们也要落地呀,分散写是可以,但是业务数据怎么分配呢,比如说用户相关信息,聪明的小伙伴一定想到了可以按照带有数值的字段分呀,比如1-100w分到A库上,100.0001w-200w分到B库上这不就解决了吗,也就是我们常说的range模式。确实,可以解决一部分场景,但是有一些场景问题没有解决,比如存储用户订单信息,如果采用这种方式会有热点问题,比如说这种方式分配的数据最近几个月的数据都会集中在B库上,而且一个用户的数据会分散在多个库中,数据需要处理聚合。假设用户查询最近几个月数据占查询请求90%,这样90%压力都集中在B库上,在崩溃边缘疯狂试探,哪天上线新功能,你没有拜拜服务器,它给你一哆嗦你一年绩效就没有了。

图片

       那这种场景如何解决呢,hash取模法,hash是一个很神奇的魔法,它可以近乎完美的让数据均匀分布,还是拿用户信息举例吧,如果用用户id做为hash函数输入,再除以你设定好的mysql master机器数量,就可以把不同用户数据分散均匀的打散到每个数据库上,而且各种用户信息也都会集中在一个库上存储,一个用户不同表操作再也不需要跨库了,再配合主从模式顺利解决读写瓶颈是不是收益多多呀,‘妈妈(老板)’再也不用担心数据库扛不住了。

图片

      别急,再教你一招得八个月年终究极大法。光有存储分片还不够,后路得想好。后续业务极速发展,数据量大量上升,满了咋办,range方式扩容最简单,直接怼机器就行,无脑扩容。hash扩容可就复杂的多了,因为原来数据库存储读取的时候是按照hash取模方式路由的,直接加机器之前的规则就乱了,新增机器后大部分数据无法命中之前的数据库了。

图片

       这里有几种比较公认的解决办法,一种是停机迁移,按照现有容量,计算好停服时间,提前做好迁移工具,事先发布停服通知,选择用户访问低谷时间段进行数据迁移。这种方式虽然最安全但是对用户体验伤害比较大,而且比较费时费力,稍有不慎就会导致核对时候数据对不上。

图片

       第二种双写配置,也就是把新加入的机器加到线上环境中,跟现有机器组成集群,sharding组件进行数据的双写,应用逻辑的查询修改主要以老库为主,通过数据同步工具慢慢的把老数据从老库同步到新库中迁移后做数据库校验然后再修改sharding规则。

图片

      第三种则是从库升级主库模式,也就是将原来主库下的从库解除主从关系,从库升级成新主库,由于主从模式使得从库和主库拥有同样的数据,所以升级上来的从库,只需要调整sharding规则分配新数据到新主库上即可,至于冗余数据,可以通过脚本慢慢删除即可,不影响提供服务,然后再将之前缺失的从库以及新主库的从库挂载上即可。这种方式操作较为简单,但是扩容的时候只能倍数扩容。

图片

       当然分库分表也还有很多弊端比如事务一致性怎么保证,跨节点join咋整等等很多,就不在这里讨论了,有兴趣的同学可以评论区讨论。以上就是对于传统数据库高并发的一些实践经验,当然想要拿八个月年终,需要全方面了解,比如像业界内以TiDB为代表的新的大数据分布式存储解决方式newsql数据库,天生支持分布式存储、还兼容mysql、支持弹性扩展、分布式事务等,感兴趣可以去官网了解其架构原理。

更多精彩内容请关注公众号:面向高薪编程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值