1号店技术部从1个人做起到今天千人级别的规模,系统支持每天亿级的访问量、单Service支持每天亿级的请求、订单支持每分钟几万单级别、Service服务可用性达到99.9999%,架构上也经历了历次演进,今天我们就从应用架构历次演进的落地点谈起。
1号店应用架构的演进大致经历了以下历程:强依赖-> Service化->业务解耦->读写分离->异步->水平/垂直拆分->服务逻辑分组等。
当然这个过程从不是串行的,永远是并行的,并且这个过程永远是在1号店这辆系统大巴行进过程中进行的,因为我们不能停车也不能刹车,而且还必须不断提速。
早 期的1号店系统,遵循简单的MVC架构,Controller层处理了所有的业务逻辑包括与DB的交互,在系统初期这种Simple的架构方便快捷,成本 低业务响应快。但当业务开始变得复杂、人员规模爆发式增长,这种强耦合强依赖带来的弊端就成了巨大的瓶颈,代码耦合度高互相冲突、出错概率和事故概率明显 提升,业务需求不能快速响应,SOA治理迫在眉睫,解耦和去依赖成为第一需求,于是Service化成为第一前提。
『 Tips 』
做Service规划首要考虑要素:
·很多人想的是采用什么RPC框架、采用什么技术,怎么让性能更高;也有人首先想的是业务怎么拆分,怎么才能更合理。
·我们首先想到的是如何做监控和问题定位。
·高可用不是一步做到的,我们的Service可用性不是一步达到99.9999%的,在这过程中一定会有很多的问题出现,怎么提前发现这些问题、出现问题后如何快速定位,这才是最重要的。这只能依赖日志,这是监控和问题定位的基础。
下 单接口业务性强,其对可用、并发、性能的要求作为技术人你懂的。我们就从这个接口开始下手,但我们没有先去分析业务,首先想的是如何定义日志系统,让以后 的监控和问题定位更简单更快捷。事实证明这个决定是对的,直到现在1号店的大部分订单相关的监控、预警、问题排查定位等完全依赖这个日志。
日志系统的设计基于以下:一是进数据库、持久化有序化,二是分类化、层次化、错误code唯一。
·进数据库、持久化有序化这个大家都理解,我曾经接手过的一个应用系统,一天下来Tomcat的log文件大小超过1G,会让你崩溃的。
·分类化、层次化、特别是错误code唯一这个是关键,它是大海航行中的那盏灯塔,让你可以瞬间定位问题位置,它给监控预警带来的好处同样伟大,可以从各个维度去做监控预警。
1号店现在有了很好的SOA中间件 – Hedwig,可支持百亿级的访问请求,它有SOA级别的日志,也很完善。但应用级别的日志我们还是建议各应用系统自己做,它的业务性、个性化是公共架构永远代替不了的。
『业务垂直拆分 』
从业务角度规划Service,从产品、用户、订单三个维度上对Service进行了规划,构成1号店应用架构上的三架马车,确立了SOA治理的框架基础。
在此基础上,又陆续衍生出促销、积分、支付等众多Service业务,在三架马车中同样会细分至如文描、价格、库存、下单、订单查询等垂直服务。
Service化是前提,Service化完成后,后面可以大刀阔斧地干了,因为业务独立了、DB读写权限收回了,哈,好像整个天下都是我的了。但,得天下易治天下难,真正的大戏在后面。
『读写分流 』
读写分离的重要性不需多讲,除了最简单的读写分离,写可以从应用层面继续细分,读也可以从应用和DB层面再细分,如订单的读写分离:
『 水平拆分 』
早在2013年,1号店实现库存的水平拆分,2014年又一举完成订单水平拆库&去Oracle迁Mysql项目。
订单水平拆库&去Oracle迁Mysql两个重量级的大项目合并为一个项目并完美无缝上线,在经济上时间上节省的是成本,在技术上体现的1号店的整体技术实力和水平。
『 服务逻辑分组 』
物理分离好处明显,但其硬件成本、维护成本高的弊端也显而易见。这时候,我们的大杀器-Hedwig又上场了,有兴趣多来了解下我们SOA中间件-Hedwig,这可是获总裁奖的项目。
Hedwig提供了服务自动注册发现、软负载均衡、节点踢出与复活、服务动态逻辑分组、请求自动重试等众多SOA框架所需的强大功能,支持并行请求、灰度发布,其背后提供的调用链路及层次关系、日志分析、监控预警等更是为SOA治理提供了强大的后勤保障。
『 业务解耦|异步 』
上面提到的读写分离、水平拆分、逻辑分组等主要是从技术层面保障,也是技术人员最喜欢的话题。业务流程的梳理、优化、改造往往不被重视,但作为应用架构,我们最不能忽视的是业务。
·我们的一个核心Service服务,性能从2年前的近200ms到现在的几十ms,从代码上、sql上的优化提升顶多占到10%,更多地优化都在业务流程的梳理改造上。
·我们曾经花费两周多的时间将一个系统的整体性能优化提升了近10倍,最后总结下来,纯技术的优化(代码或sql质量导致的性能差)几乎没有。
· 优化主要在两方面,一是架构上,如使用缓存、单SKU的循环查询改成批量查询等,这个能优化的也并不太多,因为我们的架构整体还是比较合理的;最大的优化 还是在业务梳理上,很多地方我们使用了重接口,接口里很多逻辑计算和DB查询,这些逻辑并不是所有的业务场景都需要的,但开发人员为了简单没有将业务场景 细分,导致大量不合理的调用,既浪费了服务器资源又严重影响用户体验;同样,很多地方为了一个不重要的展示或逻辑也产生大量不合理的调用,反而影响了核心 业务,这些都是最需要优化的,也是优化效果最明显的。
·异步本身不是什么高深的技术,关键是哪些业务可以走异步,这更体现架构师的业务理解能力和综合能力。
·如下单成功后给用户的消息通知、发票详细信息的生成等都可以异步,我们在这方面做了很多工作,包括和各业务方的大量沟通制定方案等,在不牺牲用户体验又保证业务流程完整的情况下,尽量走异步解耦,这对可用、性能都是极大的提升。
实例:一个下单接口定义135个错误编码
前面提到过日志和错误编码的定义,仅一个下单接口就定义了135个错误编码。接口上线后至今出现的错误编码在50-60个,也就是说有50-60处不合理或错误的地方,这个不合理或错误既有业务的又有程序的也有我们对编码定义的不合理。
目前日常每天下单出现3-5个错误编码,主要为业务性如特价商品已售完无库存等。在下单接口上线近2年后,一个之前从未出现过的错误编码跳出来了,是一个很难出现的业务场景,但通过编码马上定位问题,就不用去看代码。
做过电商核心系统的人都明白库存控制的难度,库存不准甚至超卖的问题至今还有很多电商公司没有完全解决。
这个问题也曾经困扰我们,为此还专门写了一个库存刷子的程序来刷数据,现在这个程序已基本宣告废弃了,因为我们的库存准确率达到了6个9,超卖率为0。
怎么做到的?业务、业务、业务,重要的事说三遍。3个多月对所有库存应用场景逐一排查,最终梳理出16个有问题的库存场景,并逐一协调解决,让库存形成严格的闭环线路,保证了库存的准确性。在这过程中,对库存闭环方案和对业务的理解成为关键,纯靠技术,我们能做的并不多。
业务监控首提订单监控,对订单我们从实际订单数据和Service接口调用量两个维度去做监控,保证了监控系统的稳定和准确(监控系统也会出错的),其中下单接口调用量使用的就是Service日志数据。
『 依赖查询 』
『服务监控 』
调用量实时监控
好文章,需要你的鼓励
AMD CIO的职能角色早已超越典型的CIO职务,他积极支持内部产品开发,一切交付其他部门的方案都要先经过他的体验和评判。
医学生在选择专业时,应当考虑到AI将如何改变医生的岗位形态(以及获得的薪酬待遇)。再结合专业培训所对应的大量时间投入和跨专业的高门槛,这一点就更显得至关重要。
我们拥有大量数据,有很多事情要做,然后出现了一种有趣的技术——生成式AI,给他们所有人带来的影响。这种影响是巨大的,我们在这个领域正在做着惊人的工作。