前段时间把所有重要API的日志做了分库分表改善,本打算按照这个思路写工作记录,可是想了想太局限没延伸的扩展点就选择放弃,然后再发散思维一点为什么我要分库分表,主要因为现在的API访问量已经比起刚开始构建系统的时候大得多,所以改造是有必然的,既然是这样就想写一个有系统性的改善提纲。
植入一个简单的程序背景
假设系统部署在一台AP服务器(8核16G),DB放在另一台服务器(16核32G)
有10万用户,活跃用户1万,每天高峰期4个小时,高峰期活跃的用户占比估算8成,就是8000人活跃在4小时内对系统发起请求。如果按每人每天发起20次算,那么高峰期8000人发起的请求也才16万次,平均到4小时内的每秒(14400秒),每秒也就10次请求,估算每次API请求对应3次数DB操作(CRUD),也就是每秒30次请求,按照这台数据库服务器的配置,支撑是绝对没问题的。
上面描述的系统,大概就是下面这样:
![](https://img.haomeiwen.com/i8099727/2a327df3fce32af8.jpg)
那么接下来我们开始模拟系统的一个演变过程
-
系统集群化部署
如果此时用户数开始快速增长了50倍,上升到500万。此时日活用户是50万,高峰期对系统每秒请求是500/s。然后对数据库的每秒请求数量是1500/s,这个时候会发生怎样变化?
按照上述的机器配置来说,如果系统内处理的是较为复杂的一些业务逻辑,是那种重业务逻辑系统的话是比较耗费CPU的。此时,8核16G的机器每秒请求达到500/s的时候,很可能机器CPU负载较高了,然后DB层面,以上述配置而言1500/s的高峰请求压力应该可以接受的。
这个主要是要观察DB所在服务器的磁盘负载、网络负载、CPU负载、内存负载的使用情况而定。
假设DB现在没出现问题那么需要做的一个事情,首先就是要支持系统集群化部署。可以在前面挂一个负载均衡层,把请求均衡打到系统层面,让系统可以用多台机器集群化支撑更高的并发压力。
比如说这里假设给系统增加部署一台机器,那么每台机器就只有250/s的请求了。这样一来,两台机器的CPU负载都会明显降低,要是连这个都不做,那单台机器负载越来越高的时候,极端情况下是可能出现机器上部署的系统无法有足够的资源响应请求了,然后出现请求卡死,甚至系统宕机之类的问题。
- 添加负载均衡层,将请求均衡打到系统层。
- 系统层采用集群化部署多台机器,扛住初步的并发压力。
此时的架构图大概变成下面的样子:
![](https://img.haomeiwen.com/i8099727/d7ce7111768cca94.jpg)
-
DB分库分表 + 读写分离
如果用户量继续增长,达到了1000万注册用户,然后每天日活用户是100万。那么此时对系统层面的请求量会达到每秒1000/s,按道理当然可以继续通过集群化的方式来扩容,反正前面的负载均衡层会均匀分散流量过去的。
但是,这时数据库层面接受的请求量会达到3000/s,这就有点问题了。
此时数据库层面的并发请求翻了一倍,一定会发现线上的DB负载越来越高。每次到了高峰期,磁盘IO、网络IO、内存消耗、CPU负载的压力都会很高很容易DB服务器崩溃的状况。
所以此时你必须得对系统做分库分表 + 读写分离的扩展,也就是把一个库拆分为多个库,部署在多个DB服务上,这是作为主库承载写入请求的。然后每个主库都挂载至少一个从库,由从库来承载读请求。
此时假设对数据库层面的读写并发是3000/s,其中写并发占到了1000/s,读并发占到了2000/s。那么一旦分库分表之后,采用两台数据库服务器上部署主库来支撑写请求,每台服务器承载的写并发就是500/s。每台主库挂载一个服务器部署从库,那么2个从库每个从库支撑的读并发就是1000/s。
并发量继续增长时就需要关注在DB层面。
优先考虑分区,当分区不能满足需求时,考虑分表,合理的分表对效率的提升会优于分区,最后才是分库。
此时的架构图大概如下所示:
![](https://img.haomeiwen.com/i8099727/4164e872650c1d74.jpg)
-
加入缓存集群
接下来,注册用户量还是越来越大,如果可以不停地加机器,比如说系统层面不停加机器,就可以承载更高的并发请求。
然后数据库层面如果写入并发越来越高,就扩容加数据库服务器,通过分库分表是可以支持扩容机器的,如果数据库层面的读并发越来越高,就扩容加更多的从库。
但是这里有一个很大的问题:数据库其实本身不是用来承载高并发请求的而且使用服务器越多成本越高,这明显是下策中的下策。那么现在要怎么来改善?
在高并发架构里通常都有缓存这个环节,缓存系统的设计就是为了承载高并发而生。AP承载的并发量都在每秒几万,甚至每秒数十万,对高并发的承载能力比数据库系统要高出一到两个数量级。
具体来说,写DB的时候同时写一份数据到缓存集群里,然后用缓存集群来承载大部分的读请求。这样的话,通过缓存集群,就可以用更少的机器资源承载更高的并发。这里可以根据系统的业务特性,对那种写少读多的请求,引入缓存集群。
比如读请求目前是每秒2000/s,两个从库各自抗了1000/s读请求,但是其中可能每秒1800次的读请求都是可以直接读缓存里的不怎么变化的数据。那么此时你一旦引入缓存集群,就可以抗下来这1800/s读请求,落到数据库层面的读请求就200/s。
- 不要盲目进行数据库扩容,服务器成本昂贵
- 引入缓存集群,用缓存集群抗住大量的读请求
同样,给大家来一张架构图,一起来感受一下:
![](https://img.haomeiwen.com/i8099727/fb451179faac6d72.jpg)
由于时间关系简单的一个小结
- 系统集群化
- DB层面的分库分表+读写分离
- 针对读多写少的请求,引入缓存集群
这个改善步骤不一定要这样,可以针对系统中出现的问题来专门优化解决。
初步来说,简单的一个改善阐述是讲完了,但是其实改善才刚开始。
一个完整而复杂的高并发系统架构中,会包含各种复杂的自研基础架构系统、各种精妙的架构设计(比如热点缓存架构设计、多优先级高吞吐MQ架构设计,等等)、监控服务平台、还有各种复杂系统组合而成的高并发架构整体技术方案、还有负载均衡/Web服务器等相关技术。
所以大家切记要对技术保持敬畏之心,虚心学习。
一个人可以走得很快,一群人可以走得很远。
网友评论