热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

支撑日活百万用户的高并发系统,应该如何设计其数据库架构?【石杉的架构笔记】...

点击上方蓝字, 右上角选

点击上方"蓝字", 右上角选择“设为星标”

 周一至周五早8点半!精品技术文章准时送上!

 

              精品学习资料获取通道,参见文末            

 

目录:                                                  

  • 用一个创业公司的发展作为背景引入

  • 用多台服务器来分库支撑高并发读写

  • 大量分表来保证海量数据下查询性能

  • 读写分离来支撑按需扩容及性能提升

  • 高并发下的数据库架构设计总结

 

 

“ 这篇文章,我们来聊一下对于一个支撑日活百万用户的高并系统,他的数据库架构应该如何设计?

 

看到这个题目,很多人第一反应就是:

 

分库分表啊!

 

但是实际上,数据库层面的分库分表到底是用来干什么的,他的不同的作用如何应对不同的场景,我觉得很多同学可能都没搞清楚。

 

 

 

(1)用一个创业公司的发展作为背景引入

 

假如我们现在是一个小创业公司,注册用户就20万,每天活跃用户就1万,每天单表数据量就1000,然后高峰期每秒钟并发请求最多就10。

 

天哪!就这种系统,随便找一个有几年工作经验的高级工程师,然后带几个年轻工程师,随便干干都可以做出来。

 

因为这样的系统,实际上主要就是在前期快速的进行业务功能的开发,搞一个单块系统部署在一台服务器上,然后连接一个数据库就可以了。

 

接着大家就是不停的在一个工程里填充进去各种业务代码,尽快把公司的业务支撑起来,如下图所示。

 

640?wx_fmt=png

 

 

结果呢,没想到我们运气这么好,碰上个优秀的CEO带着我们走上了康庄大道!

 

公司业务发展迅猛,过了几个月,注册用户数达到了2000万!每天活跃用户数100万!每天单表新增数据量达到50万条!高峰期每秒请求量达到1万!

 

同时公司还顺带着融资了两轮,估值达到了惊人的几亿美金!一只朝气蓬勃的幼年独角兽的节奏!

 

好吧,现在大家感觉压力已经有点大了,为啥呢?

 

因为每天单表新增50万条数据,一个月就多1500万条数据,一年下来单表会达到上亿条数据。

 

经过一段时间的运行,现在咱们单表已经两三千万条数据了,勉强还能支撑着。

 

但是,眼见着系统访问数据库的性能怎么越来越差呢,单表数据量越来越大,拖垮了一些复杂查询SQL的性能啊!

 

然后高峰期请求现在是每秒1万,咱们的系统在线上部署了20台机器,平均每台机器每秒支撑500请求,这个还能抗住,没啥大问题。

 

但是数据库层面呢?

 

如果说此时你还是一台数据库服务器在支撑每秒上万的请求,负责任的告诉你,每次高峰期会出现下述问题:

 

  • 你的数据库服务器的磁盘IO、网络带宽、CPU负载、内存消耗,都会达到非常高的情况,数据库所在服务器的整体负载会非常重,甚至都快不堪重负了

 

  • 高峰期时,本来你单表数据量就很大,SQL性能就不太好,这时加上你的数据库服务器负载太高导致性能下降,就会发现你的SQL性能更差了

 

  • 最明显的一个感觉,就是你的系统在高峰期各个功能都运行的很慢,用户体验很差,点一个按钮可能要几十秒才出来结果

 

  • 如果你运气不太好,数据库服务器的配置不是特别的高的话,弄不好你还会经历数据库宕机的情况,因为负载太高对数据库压力太大了

 

 

 

(2)多台服务器分库支撑高并发读写

 

首先我们先考虑第一个问题,数据库每秒上万的并发请求应该如何来支撑呢?

 

要搞清楚这个问题,先得明白一般数据库部署在什么配置的服务器上。

 

通常来说,假如你用普通配置的服务器来部署数据库,那也起码是16核32G的机器配置。

 

这种非常普通的机器配置部署的数据库,一般线上的经验是:不要让其每秒请求支撑超过2000,一般控制在2000左右。

 

控制在这个程度,一般数据库负载相对合理,不会带来太大的压力,没有太大的宕机风险。

 

所以首先第一步,就是在上万并发请求的场景下,部署个5台服务器,每台服务器上都部署一个数据库实例。

 

然后每个数据库实例里,都创建一个一样的库,比如说订单库。

 

此时在5台服务器上都有一个订单库,名字可以类似为:db_order_01,db_order_02,等等。

 

然后每个订单库里,都有一个相同的表,比如说订单库里有订单信息表,那么此时5个订单库里都有一个订单信息表。

 

比如db_order_01库里就有一个tb_order_01表,db_order_02库里就有一个tb_order_02表。

 

这就实现了一个基本的分库分表的思路,原来的一台数据库服务器变成了5台数据库服务器,原来的一个库变成了5个库,原来的一张表变成了5个表。

 

然后你在写入数据的时候,需要借助数据库中间件,比如sharding-jdbc,或者是mycat,都可以。

 

你可以根据比如订单id来hash后按5取模,比如每天订单表新增50万数据,此时其中10万条数据会落入db_order_01库的tb_order_01表,另外10万条数据会落入db_order_02库的tb_order_02表,以此类推。

 

这样就可以把数据均匀分散在5台服务器上了,查询的时候,也可以通过订单id来hash取模,去对应的服务器上的数据库里,从对应的表里查询那条数据出来即可。

 

依据这个思路画出的图如下所示,大家可以看看。

 

640?wx_fmt=png

 

 

做这一步有什么好处呢?

 

第一个好处,原来比如订单表就一张表,这个时候不就成了5张表了么,那么每个表的数据就变成1/5了。

 

假设订单表一年有1亿条数据,此时5张表里每张表一年就2000万数据了。

 

那么假设当前订单表里已经有2000万数据了,此时做了上述拆分,每个表里就只有400万数据了。

 

而且每天新增50万数据的话,那么每个表才新增10万数据,这样是不是初步缓解了单表数据量过大影响系统性能的问题?

 

另外就是每秒1万请求到5台数据库上,每台数据库就承载每秒2000的请求,是不是一下子把每台数据库服务器的并发请求降低到了安全范围内

 

这样,降低了数据库的高峰期负载,同时还保证了高峰期的性能。

 

 

 

(3)大量分表来保证海量数据下的查询性能

 

但是上述的数据库架构还有一个问题,那就是单表数据量还是过大,现在订单表才分为了5张表,那么如果订单一年有1亿条,每个表就有2000万条,这也还是太大了。

 

所以还应该继续分表,大量分表。

 

比如可以把订单表一共拆分为1024张表,这样1亿数据量的话,分散到每个表里也就才10万量级的数据量,然后这上千张表分散在5台数据库里就可以了。

 

在写入数据的时候,需要做两次路由,先对订单id hash后对数据库的数量取模,可以路由到一台数据库上,然后再对那台数据库上的表数量取模,就可以路由到数据库上的一个表里了。

 

通过这个步骤,就可以让每个表里的数据量非常小,每年1亿数据增长,但是到每个表里才10万条数据增长,这个系统运行10年,每个表里可能才百万级的数据量。

 

这样可以一次性为系统未来的运行做好充足的准备,看下面的图,一起来感受一下:

 

640?wx_fmt=png

 

 

 

(4)读写分离来支撑按需扩容以及性能提升

 

这个时候整体效果已经挺不错了,大量分表的策略保证可能未来10年,每个表的数据量都不会太大,这可以保证单表内的SQL执行效率和性能。

 

然后多台数据库的拆分方式,可以保证每台数据库服务器承载一部分的读写请求,降低每台服务器的负载。

 

但是此时还有一个问题,假如说每台数据库服务器承载每秒2000的请求,然后其中400请求是写入,1600请求是查询。

 

也就是说,增删改的SQL才占到了20%的比例,80%的请求是查询。

 

此时假如说随着用户量越来越大,假如说又变成每台服务器承载4000请求了。

 

那么其中800请求是写入,3200请求是查询,如果说你按照目前的情况来扩容,就需要增加一台数据库服务器.

 

但是此时可能就会涉及到表的迁移,因为需要迁移一部分表到新的数据库服务器上去,是不是很麻烦?

 

其实完全没必要,数据库一般都支持读写分离,也就是做主从架构。

 

写入的时候写入主数据库服务器,查询的时候读取从数据库服务器,就可以让一个表的读写请求分开落地到不同的数据库上去执行。

 

这样的话,假如写入主库的请求是每秒400,查询从库的请求是每秒1600,那么图大概如下所示。

 

640?wx_fmt=png

 

 

写入主库的时候,会自动同步数据到从库上去,保证主库和从库数据一致。

 

然后查询的时候都是走从库去查询的,这就通过数据库的主从架构实现了读写分离的效果了。

 

现在的好处就是,假如说现在主库写请求增加到800,这个无所谓,不需要扩容。然后从库的读请求增加到了3200,需要扩容了。

 

这时,你直接给主库再挂载一个新的从库就可以了,两个从库,每个从库支撑1600的读请求,不需要因为读请求增长来扩容主库。

 

实际上线上生产你会发现,读请求的增长速度远远高于写请求,所以读写分离之后,大部分时候就是扩容从库支撑更高的读请求就可以了。

 

而且另外一点,对同一个表,如果你既写入数据(涉及加锁),还从该表查询数据,可能会牵扯到锁冲突等问题,无论是写性能还是读性能,都会有影响。

 

所以一旦读写分离之后,对主库的表就仅仅是写入,没任何查询会影响他,对从库的表就仅仅是查询。

 

 

 

(5)高并发下的数据库架构设计总结

 

其实从大的一个简化的角度来说,高并发的场景下,数据库层面的架构肯定是需要经过精心的设计的。

 

尤其是涉及到分库来支撑高并发的请求,大量分表保证每个表的数据量别太大,读写分离实现主库和从库按需扩容以及性能保证。

 

这篇文章就是从一个大的角度来梳理了一下思路,各位同学可以结合自己公司的业务和项目来考虑自己的系统如何做分库分表应该怎么做。

 

另外就是,具体的分库分表落地的时候,需要借助数据库中间件来实现分库分表和读写分离,大家可以自己参考 sharding-jdbc 或者 mycat 的官网即可,里面的文档都有详细的使用描述。

 

 

扫描下方二维码,备注:“资料”,获取更多 “秘制” 精品学习资料

 

640?wx_fmt=png

640?wx_fmt=gif

End

 

推荐阅读

  • 精品专栏之微服务系列

  • 精品专栏之分布式系列

  • 精品专栏之亿级流量架构演进系列

  • 精品专栏之并发系列

  • 精品专栏之大数据系列

  • 精品专栏之Java进阶面试系列

 

一大波微服务、分布式、高并发、高可用原创系列文章正在路上。

 

欢迎扫描下方二维码,持续关注:

640?wx_fmt=jpeg

 

石杉的架构笔记(id:shishan100)

十余年BAT架构经验倾囊相授

 

 


640


推荐阅读
  • Unity3D引擎的体系结构和功能详解
    本文详细介绍了Unity3D引擎的体系结构和功能。Unity3D是一个屡获殊荣的工具,用于创建交互式3D应用程序。它由游戏引擎和编辑器组成,支持C#、Boo和JavaScript脚本编程。该引擎涵盖了声音、图形、物理和网络功能等主题。Unity编辑器具有多语言脚本编辑器和预制装配系统等特点。本文还介绍了Unity的许可证情况。Unity基本功能有限的免费,适用于PC、MAC和Web开发。其他平台或完整的功能集需要购买许可证。 ... [详细]
  • 熟练掌握Spring Cloud,终于成为Java工程师的面试门槛 ... [详细]
  • BPM是什么软件?1、BPM是BusinessProcessManagement的简称,译为业务流程管理,它是一种以规范化的构造端到端的卓越业务流程为中心以持续的提高组织业务绩效为 ... [详细]
  • 说出来你可能不信,我用三天做了一个完整的项目
    Java在人工智能中能起到什么作用?作为编程语言中的扛把子,Java20多年稳定不倒,就在于它的稳定性,维护成本极低。这使得 ... [详细]
  • SOA架构理解理解SOA架构,了解ESB概念,明白SOA与微服务的区别和联系,了解SOA与热门技术的结合与应用。1、面向服务的架构SOASOA(ServiceOrien ... [详细]
  • 第四单元和课程总结:简单的架构设计意识
    一、第四单元架构设计总结第一次作业由于需要按名查找类图模型,于是建立"Class"类进行管理由于方法具有参数导致类中存在二级结构 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • 微信商户扫码支付 java开发 [从零开发]
    这个教程可以用作了解扫码支付的整体运行过程,已经实现了前端扫码,记录订单,回调等一套完整的微信扫码支付。相关链接:微信支 ... [详细]
  • [翻译]微服务设计模式5. 服务发现服务端服务发现
    服务之间需要互相调用,在单体架构中,服务之间的互相调用直接通过编程语言层面的方法调用就搞定了。在传统的分布式应用的部署中,服务地 ... [详细]
  • TiDB | TiDB在5A级物流企业核心系统的应用与实践
    TiDB在5A级物流企业核心系统的应用与实践前言一、业务背景科捷物流概况神州金库简介二、现状与挑战神州金库现有技术体系业务挑战应对方案三、TiDB解决方案测试迁移收益问题四、说在最 ... [详细]
  • 后台自动化测试与持续部署实践
    后台自动化测试与持续部署实践https:mp.weixin.qq.comslqwGUCKZM0AvEw_xh-7BDA后台自动化测试与持续部署实践原创 腾讯程序员 腾讯技术工程 2 ... [详细]
  • Java工程师书单(初级,中级,高级)
    简介怎样学习才能从一名Java初级程序员成长为一名合格的架构师,或者说一名合格的架构师应该有怎样的技术知识体系,这是不仅一个刚刚踏入职场的初级程序员也是工作一两年之后开始迷茫的程序 ... [详细]
  • 软件测试工程师,需要达到什么水平才能顺利拿到 20k+ 无压力?
    前言最近看到很多应届生晒offer,稍有名气点的公司给出的价格都是一年30多W或者月薪20几k,相比之下工作几年的自己薪资确实很寒酸.根据我自己找工作经历,二线城市一般小公司招聘 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有