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

目录:sql

  • 用一个创业公司的发展做为背景引入
  • 用多台服务器来分库支撑高并发读写
  • 大量分表来保证海量数据下查询性能
  • 读写分离来支撑按需扩容及性能提高
  • 高并发下的数据库架构设计总结

 

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

看到这个题目,不少人第一反应就是:安全

分库分表啊!服务器

可是实际上,数据库层面的分库分表究竟是用来干什么的,他的不一样的做用如何应对不一样的场景,我以为不少同窗可能都没搞清楚。网络


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

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

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

由于这样的系统,实际上主要就是在前期快速的进行业务功能的开发,搞一个单块系统部署在一台服务器上,而后链接一个数据库就能够了。高并发

接着你们就是不停的在一个工程里填充进去各类业务代码,尽快把公司的业务支撑起来,以下图所示。性能

 

 

 

 

结果呢,没想到咱们运气这么好,碰上个优秀的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取模,去对应的服务器上的数据库里,从对应的表里查询那条数据出来便可。

依据这个思路画出的图以下所示,你们能够看看。

 

 

 

 

作这一步有什么好处呢?

第一个好处,原来好比订单表就一张表,这个时候不就成了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年,每一个表里可能才百万级的数据量。

这样能够一次性为系统将来的运行作好充足的准备,看下面的图,一块儿来感觉一下:

 

 

 

 


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

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

而后多台数据库的拆分方式,能够保证每台数据库服务器承载一部分的读写请求,下降每台服务器的负载。

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

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

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

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

可是此时可能就会涉及到表的迁移,由于须要迁移一部分表到新的数据库服务器上去,是否是很麻烦?

其实彻底不必,数据库通常都支持读写分离,也就是作主从架构。

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

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

 

 

 

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

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

如今的好处就是,假如说如今主库写请求增长到800,这个无所谓,不须要扩容。而后从库的读请求增长到了3200,须要扩容了。

这时,你直接给主库再挂载一个新的从库就能够了,两个从库,每一个从库支撑1600的读请求,不须要由于读请求增加来扩容主库。

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

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

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


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

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

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

这篇文章就是从一个大的角度来梳理了一下思路,各位同窗能够结合本身公司的业务和项目来考虑本身的系统如何作分库分表应该怎么作。

另外就是,具体的分库分表落地的时候,须要借助数据库中间件来实现分库分表和读写分离,你们能够本身参考 sharding-jdbc 或者 mycat 的官网便可,里面的文档都有详细的使用描述。

End

欢迎工做一到五年的Java工程师朋友们加入Java高级架构:964357187 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用本身每一分每一秒的时间来学习提高本身,不要再用"没有时间“来掩饰本身思想上的懒惰!趁年轻,使劲拼,给将来的本身一个交代!

相关文章
相关标签/搜索