从单一WAR到多活, 记述一个创业公司的架构演变
从单一WAR到多活, 记述一个创业公司的架构演变
本故事纯属虚构,如有雷同,实属巧合
程 是一个爱折腾,喜欢交朋友的程序员。
某一天,程一个朋友介绍了另外一个朋友 创 给他,创说他有个点子,可以改变世界,现在就差一个程序员。程看了创的PPT,觉得还不错,反正也没妹子,平时下班回家或者周末也没事干,就答应创,做他的合伙人,给他开发网站。
单一垂直架构
程把他自己在大学的时候做的基于Java的考试管理系统,拿来改了改,又自学了一些前端,三个月后,第一个版本的网站上线了。这个东西的后台大概这个样子,所有的东西都部署在一台服务器上。
负载+垂直架构
上线后的半年,为了适应业务的变更,网站做了多次升级和新功能的研发。伴随着代码越来越庞大,注册用户越来越多,有时候要卡半天,才能刷出页面。创又多花几倍的预算在技术上,买了几台新服务器。然后这套系统变成了下面的样子,Mysql终于可以单独放在一台服务器上了,使用负载均衡后,可以把服务器实例(war)拷贝后部署到几台机器上了。
升级后,瞬间快了很多。
分布式服务架构
后来,这个公司拿到了天使投资,程也全职加入了,身份是CTO,而理所当然的,创做了CEO。陆续也有运营和市场的合伙人加入,日活有几万了。程也不用自己写前端了,因为招了2个专门的前端工程师,还有另外2个做服务器的小伙子。市场变化很多,每天都有新需求,每天都可能上线新功能。
但是,当前这样的服务器代码体系,让他越来越力不从心。
1. 这么一坨庞大的代码融在一起,维护成本和新人学习成本都是特别高的。 2. 想招一个实习生,但是如果开放给他权限就是所有代码,真担心这个实习生把代码拿去卖了。 3. 代码构建的时间越来越长,程序员最不喜欢的就是等了。 4. 发布成本也很高,因为每次发布都是全量发布。有些核心功能,需要全天服务用户,所以白天几乎不可能发布。即时发布一个无关紧要的功能,也要等到晚上,出了Bug还要赶紧修复,长期熬夜,真是觉得这个世界充满恶意。
不能再这样下去了......
其实程很早就听过分布式架构(SOA),也知道主流的公司都在用这些。但是现在业务代码已经十分庞大了,至少十几万,并且有大量重复和“不敢动的”代码,重构成SOA,至少要两个月,公司新需求不断,怎么可能。
经过一个月的挣扎,真心觉得不能忍了,决定升级架构成SOA,调研后发现阿里的开源框架Dubbo (dubbo.io) 好像使用的蛮多,文档也挺全的,所以决定用它。
重构前,首先梳理了一下业务,按照业务相关性,拆分成若干的底层SOA服务和API层服务。这个重构大概进行了2个月,CEO没技术背景,完全不知道他们提的SOA是个啥,新需求不能被满足,已经处于崩溃边缘。
终于,新架构上线了,它大概长成这个样子。
这里,每个服务包括API服务和基础的SOA服务都可以部署在不同的机器上,他们之间的发现是通过Zookeeper集群协调的。启动一个服务后,它就会注册自己到Zookeeper上,服务调用方被通知,新的服务实例上线。服务调用方持有一个服务的多个调用实例,采用某种策略进行负载。
可以按照业务需求,有选择的扩容指定服务,举个栗子,例如商城做双十一活动,有很多秒杀商品,那么只需要多部署几个和商城相关的服务即可。如果按照之前的架构设计,所有功能都在一个war中,只能对所有功能扩容,浪费计算资源。
当然,还有一些任务被改造成定时任务,就是图中的Scheduled模块,例如结算等,这样运营或者程序员就不用大半夜起来做事了。
分库分表,读写分离
半年后,公司又融了几千万的A轮,用户数进一步扩大。高峰时段越来越卡,各种Log分析系统时间和分析Mysql慢日志发现,因为数据量越来越多,并发数越来越大,主存储已经有点Hold不住了。并且程越来越担心万一哪天,那台Mysql机器硬盘出故障,废了,公司的所有的数据就都没了。
后来无意见,程发现了Mycat(mycat.io) 这个数据库中间件,原来还以利用它做分库分表,读写分离这些自己实践起来十分困难的高级Feature。
经过了差不多一个月的调研,实践,测试,升级后的Mysql集群变成了如下的样子。
做了分库分表后,再也不用担心太多数据把单一Mysql服务器硬盘撑满的问题了,并且也更方便了权限管理。启用Slave从节点后,也不用担心单一主节点硬盘故障后,数据的丢失问题了。读写分离后,前端访问速度也快了很多,增删改查被分散到不同的机器,单节点的效率瓶颈有了很明显的缓解。
DRC(Data Replication Center)
伴随着业务种类越来越多,数据越来越多,依赖Mysql的索引的搜索早就显得力不从心。为了性能,只能支持某个字段的StartWith搜索。包含和模糊搜索都不能做,所以就用了Elastic Search做通用搜索引擎。为了进一步提升读效率,也把很多登录信息和用户好友关系这些经常读的数据,放入Redis中做缓存。
同一份数据,既要放入ES,还要放入Redis,早期这个功能实现大概如下:
更新代码往往要关心缓存,同步ES数据,如果同步间隙过长,会有数据延迟,如果同步间隙太短,还要增加DB负担。并且伴随这个业务变多,越来越多这样的操作:从一个表中全量拉取更新数据,做进一步业务处理,给业务库造成很多额外的压力。
如果主数据变动,就把变动发送到一个中心,感兴趣的一·方只要订阅这些消息,就可以实现自己的逻辑,实时性高的同时,不会给业务库造成任何压力。于是DRC诞生了:
可以理解DRC Replicator模拟了一个Mysql Slave,从主节点拉binlog,然后解析binlog,并将结果发送到消息队列中。
而感兴趣的程序,可以去订阅消息,然后执行相应的更新,这样就把更新缓存的事情和业务代码解耦了,更新ES这种操作也可以做到既实时性高,也不用经常去Mysql库中扫描表了。当然DRC还有一个重要的应用,它也是多活的核心组件之一。
多活
伴随用户体量进一步提高,交易量的暴增,简单的数据备份,已经不能很好的满足需求了。如果机房宕机,依然会导致服务不可用。
另外,所有的流量都打到机房的服务集群,也会导致一定的系统瓶颈。可能更理想的方式是:一个北京的用户下单,他的整个业务流都落在北京的机房;上海的用户下单,也希望所有的数据落在上海的机房,两个机房的主数据互备,同时满足数据的一致性。其中某个机房挂掉后,所有的流量切到另外一个机房。
而对于强一致性的数据,例如用户表存在用户名的uniq索引,对于这类数据,可以放在一个倍成为全局数据的机房,所有写落在这里,其他机房只是执行备份。
就这样,随着用户的逐渐增多,融资一次一次到来,团队越来越多,业务线越来越多,架构的也一次一次升级演化。路已经走了很远,并且伴随着越走越远,未来可能还有更多的升级和演化。
这个架构演化的故事,讲完了。如有陈述不当或错误,欢迎留言讨论~
传送门 : https://zhuanlan.zhihu.com/p/27903657
从单一WAR到多活, 记述一个创业公司的架构演变的更多相关文章
- [Android]一个干净的架构(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5276587.html 一个干净的架构 原文:https://b ...
- 、web前端的这么知识应该是怎样的一个知识体系架构?
.web前端的这么知识应该是怎样的一个知识体系架构?之前我以为可以以W3C为纲要,把W3C的东西学会了就够了.后来发现我错了,W3C还不全面. 真正全面的覆盖了web前端知识体系的东西是——浏览器内核 ...
- 【转】傅盛:怎样做一个创业公司CEO?
摘要 : 傅盛High聊会,泉灵姐姐给的命题作文.怎样做一个创业公司CEO,核心还是思维模式. 这次傅盛High聊会,泉灵姐姐给我的命题作文.创业要如何开始,本质还是思维模式.首先学会把一个开放式问题 ...
- 我发起了一个 支持 ServerFul 架构 的 .Net 开源项目 ServerFulManager
大家好, 我发起了一个 支持 ServerFul 架构 的 .Net 开源项目 ServerFulManager . ServerFulManager 的 目标 是 实现一个 支持 ServerFu ...
- 多个微信小程序一个服务端架构
由于某些特定的业务场景,当多个小程序需要一个服务端后台提供数据时,大家可能想到是HTTP路由.是的,实际上我们使用微服务的GateWay网关也是一样的,如下图微服务架构: 网关GateWay的作用在于 ...
- SaltStack 是一个服务器基础架构集中化管理平台
SaltStack详细部署 一.基础介绍============================================================================== ...
- 成为一个高级java架构师所需要具备那些技能呢?
一.什么是架构师 所谓架构师,思考的是全局的东西,是如何组织你的系统,以达到业务要求,性能要求,具备可扩展性(scalability),可拓展性(extendability),前后兼容性等.可能涉及到 ...
- 2020年如何成为一个高级AVA架构师(50W~100W年薪)
2020年如何成为一个高级AVA架构师(50W~100W年薪)
- 实现类似QQ单一账户登录,在另一个地方登录后在原登录窗口提示下线
首先,使用框架做的最好,可以在框架页直接做一次就好了 再登陆成功后保存session的代码后添加以下代码: 注意:需要引入命名空间using System.Collections; SetApplic ...
随机推荐
- 使用OkHttpClient处理json请求处理的方式
今天遇到一个问题,重构老系统时,前端传递的参数是一个json,controller层可以用@ResponseBody来接收. 因为新系统用的是spring cloud这一套,调用其他服务使用的是fei ...
- hbase操作
名称命令表达式 创建表create '表名称','列簇名称1','列簇名称2'....... 添加记录put '表名称', '行名称','列簇名称:','值' 查看记录get '表名称','行名称' ...
- 关于haproxy多域名证书的配置
frontend main bind *: bind *: ssl crt /etc/haproxy/kong.com.pem crt /etc/haproxy/51yijI.com.pem no-s ...
- tmux用于恢复远程屏幕
1.我主要用tmux在远程登陆后,恢复以前会话时候用. 2.tmux创建新会话: tmux new -s 会话名 3.返回控制台: Ctrl+b d ,Ctrl+b命令是tmux前置命令,每次都要先输 ...
- 【Unity】6.3 通过 C# 脚本创建和访问游戏对象
分类:Unity.C#.VS2015 创建日期:2016-04-16 一.简介 在游戏开发过程中,脚本不但需要访问脚本所在的游戏对象的组件,还经常需要访问和控制真他游戏对象.另外,根据项目需求,还可能 ...
- 【Unity】3.6 导入图片资源
分类:Unity.C#.VS2015 创建日期:2016-04-05 一.简介 Unity支持的图像文件格式非常多,包括TIF.PSD.TCA.JPC.PNG.GlF.BMP.IFF.PICT.DDS ...
- 【Android】1.0 第1章 C#之Android手机App开发
分类:C#.Android.VS2015:创建日期:2016-01-20 目前Android在全世界市场上大约有75%的占有率,国人Android手机的持有比例更甚,甚至达到90%以上.因此搞计算机的 ...
- Chunk
Chunk是一系列语句,Lua执行的每一块语句,比如一个文件或者交互模式下的每一行都是一个Chunk. 每个语句结尾的分号(;)是可选的,但如果同一行有多个语句最好用:分开 a = 1 b = a ...
- 每日英语:China to Move Slowly on One-Child Law Reform
BEIJING—China's family-planning agency is projecting a slow rollout for an easing of its one-child p ...
- Windows下断言的类型及实现
一.内容综述 本文主要介绍Windows下断言assert的实现,并总结断言的不同应用准则.最后给出一个windows自定义断言的方法. 本文行文参考<Debugging Windows Pro ...