[案例教学]如何设计高并发分布式系统?
高并发系统肯定要干的一些事儿
如果我们的产品目标用户大概是几百上千人,那么我们可能部署一个节点就能满足日常需求,此时我们可能会面临的一个问题是在发布时,可能会出现服务不可用的情况。或者一些非预期的情况,导致服务挂掉。为了实现高可用,我们逐步需要引入负载均衡,缓存,消息队列,搜索引擎等。在引入这些中间件后,我们的分布式系统就基本形成了,具备一定的高可用,抗并发的特性。
分页式架构总结.jpg
HAProxy/Keepalived/Nginx接入层
接入层实现软负载均衡。可以按照轮询或短时间(比如2个小时)粘连的方式实现将流量分发到后端的服务节点上。此时需要服务节点具备无状态的特性,我们要么不用Session,要么使用分布式Session。
应用集群
为了实现高可用,我们必须对服务节点进行冗余化设计,即部署多个节点来提供服务。现在最流行的Kubernetes可以对这些提供更好的支持,比如弹性扩容,灰度发布,运行监控等。
系统拆分
将一个系统拆分为多个子系统,用 Spring Cloud 来搞。然后每个系统连一个数据库,这样本来就一个库,现在多个数据库,不也可以扛高并发么。
服务网关
在将系统拆分成多个内聚的微服务后,你会发现需要有一些通用的共享服务,比如服务鉴权,统一异常处理,统一服务返回结果,容灾,降级,限流等。
缓存
缓存,必须得用缓存。大部分的高并发场景,都是读多写少,那你完全可以在数据库和缓存里都写一份,然后读的时候大量走缓存不就得了。毕竟人家 redis 轻轻松松单机几万的并发。所以你可以考虑考虑你的项目里,那些承载主要请求的读场景,怎么用缓存来抗高并发。
MQ
MQ,必须得用 MQ。可能你还是会出现高并发写的场景,比如说一个业务操作里要频繁搞数据库几十次,增删改增删改,疯了。那高并发绝对搞挂你的系统,你要是用 redis 来承载写那肯定不行,人家是缓存,数据随时就被 LRU 了,数据格式还无比简单,没有事务支持。所以该用 mysql 还得用 mysql 啊。那你咋办?用 MQ 吧,大量的写请求灌入 MQ 里,排队慢慢玩儿,后边系统消费后慢慢写,控制在 mysql 承载范围之内。所以你得考虑考虑你的项目里,那些承载复杂写业务逻辑的场景里,如何用 MQ 来异步写,提升并发性。MQ 单机抗几万并发也是 ok 的,这个之前还特意说过。
分库分表
分库分表,可能到了最后数据库层面还是免不了抗高并发的要求,好吧,那么就将一个数据库拆分为多个库,多个库来扛更高的并发;然后将一个表拆分为多个表,每个表的数据量保持少一点,提高 sql 跑的性能。
读写分离
读写分离,这个就是说大部分时候数据库可能也是读多写少,没必要所有请求都集中在一个库上吧,可以搞个主从架构,主库写入,从库读取,搞一个读写分离。读流量太多的时候,还可以加更多的从库。
ElasticSearch
Elasticsearch,简称 es。es 是分布式的,可以随便扩容,分布式天然就可以支撑高并发,因为动不动就可以扩容加机器来扛更高的并发。那么一些比较简单的查询、统计类的操作,可以考虑用 es 来承载,还有一些全文搜索类的操作,也可以考虑用 es 来承载。
分布式系统的更多挑战
如果我们的产品目标用户是几万几十万,甚至是上亿时?我们又该如何设计我们的系统架构,如何拆分模块,如何做容灾、降级、限流呢?如何面临缓存雪崩,尖峰流量,JVM无响应呢?如何有效监控,评估系统运行情况?如何进行JVM调优呢?
关于中台架构
我对中台架构的浅显理解就是提供共享服务,在集团内部将通用化服务快速输出到其它产品线,这里提到的通用化服务指类似直播功能,即时通信功能,通用权限管理系统等,具体的形态可能是一个服务,一个SDK, 一个前端组件,一个系统等。中台架构实现难度很高,在互联网企业中,很多还是复制代码,快速开发出产品为第一要务。真正要落实中台架构的话,对公司组织架构,产品能力,技术研发能力要求很高。像阿里巴巴这种逐步发展起来的集团公司才有这种幸运,更多公司可能只能站在巨人的肩膀上,稳扎稳打做好产品和服务,不要意味地追求中台架构。
参考资料
关注公众号交流学习
在这里分享一些项目实战过程中遇到过的问题及解决方案。分享学习到的分布式架构及核心技术细节。
关注Java分布式架构实战, 持续精进
加我微信,聊一聊
联系我,学习交流