转转孙玄:微服务架构下,如何打造二手交易平台

存储 云计算
在大会的云计算基础架构与实践分论坛上,转转公司架构算法部负责人孙玄带来了《微服务架构下,如何打造二手交易平台》的主题演讲。他从何为微架构服务谈起,从垂直领域、业务模式和引入分布式事务解决方案三个方面与大家分享了如何做好微架构服务。

   由中国电子技术标准化研究院主办、51CTO承办的“第七届中国云计算标准和应用大会”于2018年1月4日至1月5日在北京成功召开。本次大会全面展示我国云计算国家标准研制工作的成果,解读国内云计算产业政策,报告云计算标准化工作的重要进展。同时,大会还重磅发布了国家开源领域的标准化产物,分享了云计算***的技术趋势和应用创新成效,并颁发了云计算产品及解决方案第五批测评证书。此外,第二届中国优秀云计算开源案例评选结果也在大会现场公布。

[[216347]]

  在大会的云计算基础架构与实践分论坛上,转转公司架构算法部负责人孙玄带来了《微服务架构下,如何打造二手交易平台》的主题演讲。他从何为微架构服务谈起,从垂直领域、业务模式和引入分布式事务解决方案三个方面与大家分享了如何做好微架构服务。作为本场论坛的***一名演讲嘉宾,虽然天色已晚,但精彩的内容分享仍然吸引了现场所有观众的驻足聆听。

  以下为演讲实录:

  大家下午好!

  到这个时间点了,大家还坐在这里听我讲非常不容易,其实刚才刘喆讲的非常精彩,他说这个会就不应该讲比较技术的东西。刚好我今天准备的这个东西分两部分,一部分是用来吹牛的,但是还有一部分是干货,干货部分刘喆说了,我们应该讲一些更加宏观的东西,所以技术的东西我们尽量少讲。

  今天讲一下在整个微服务架构下,我们整个二手交易平台怎么样打造一些云基础设施?

  首先,允许我做个自我介绍,我此前一直在58待了很多年,58成长比较快,成为整个58集团***的架构师,后来带领大家做一些在技术上比较难啃的骨头。当年为什么加入58,其实比较有意思。我2011年在百度,后来想离开百度,去哪里呢?其实不知道,当时猎头就问我,你想不想去58?我当时说也可以,但是我不知道58是什么东西,我唯一知道每天杨幂在整个公交上和地铁上说58同城一个神奇的网站,我想既然神奇,我就来了,一待就是很多年。我在58经历比较简单,基本上最开始做一个类似于一个电商的聊天的工具,后来就做转转的产品。

  我在百度其实是在做百度空间,大家知道这个产品吗?不知道,你们知道的同学都暴露年轻了。在此前在浙大读书,后面因为有很多积累,所以代表公司做了很多次分享。基本上业内的大会,我能刷脸的地方都刷过了,包括整个AI,包括整个架构的大会其实的刷比较多,为什么最近刷AI?我其实个人的经历,架构放了一部分,但是做电商其实更重要的是在算法方面,比如说通过一些机器学习,在整个推荐和搜索上产生一定的订单万花,因为这部分现在是我负责,我个人更多精力放在算法上面,有兴趣的同学可以交流,也是我个人的一些介绍。

  谈到微服务架构首先聊聊微服务架构是一个什么东西,围绕微服务架构下二手交易平台做哪些基础设施,这里选择两个比较有典型的案例跟大家去讲一下,比如说在二手交易平台下整个分布式怎么设计,我们整个事务如何去做?讲之前首先聊一下这个东西,这个东西大家都见过没有?这其实是我们的一个logo,因为我们是做二手的,我们要解决一个从“买买买”到“卖卖卖”的问题,我原来在朋友圈看到一句话觉得挺有意思的,其实也是解决同买买买到卖卖卖的问题,当然也是在共享经济时代的流转,我们更鼓励你不用的东西可以在二手平台上卖出去,这样至少你可以换点钱,至少你对钱其实是不讨厌的。

  按垂直领域去做微服务架构

  我们讲到微服务,不得不提在整个微服务时代有一个人提出这个架构,这个架构是马丁·福勒。微服务架构的思想很早都有,真正提出来是在2014年,既然是一种架构模式,必然会遵循一些规范或者架构设计的理念,大家可以看,首先微服务是一些小服务的组合。什么叫小服务的组合呢?有一次在一个大会的会议下交流时,有位老师说能够做到定量的去做到微服务,我说你们是怎么样做到的?他们老板说,我们就按照代码行来做,一千行就定义为一个微服务。他问我行不行,假设你们的代码行数是1001行你怎么做?他回答好像我们还没遇到这个问题。

  我们要做微服务,你们一定听说过什么领域驱动设计,这是很大的理论,实际过程中怎么做呢?就可以按照整个业务的垂直领域去参与。我们做二手交易,我们有用户体系,我们用商品体系,我们有交易体系、搜索体系、交易体系,垂直拆,用户是一块,商品是一块,推荐一块,拆完之后,每一块就是微服务,这样拆完就OK了吗?当然不OK,搜索如果拆完之后所有的逻辑、数据访问都在一起,必然造成你的模块的功能非常臃肿,我们需要在水平方向做一个拆分,可以拆成网关,业务逻辑层和DB来做,我们在业界做无非就是垂直拆分和水平拆分的东西,来做这一块,这块是比较简单的。

  最终我们拆出来,我们真正拆的话,其实一样,比如上面是我们整个客户端,比如说IOS和安卓,对下面是整个网关,网关下面是业务逻辑层,再下面是数据访问,再下面是TB做这一块,垂直方向做了垂直拆分,水平方向又做了水平拆分。在我看来同整个架构模式上,你的微服务架构无非做了一个垂直拆分,加上一个水平拆分,当然它最难的其实不在你的水平拆分,而是在于你的垂直拆分,所以这个比较简单。我们整个微服务,他的业务架构这时候应该按照你的业务领域模型进行拆分,拆分完之后我们再去做一个水平拆分就OK了,这个其实是比较简单的。

  另外一块,我们整个二手交易平台其实它是电商,既然有电商的话,电商该有的东西它都有,所以我们这个模块其实也是比较多的。大家可以看一下,从下面整个的运维支撑,包括我们的发布系统,以及我们整个的信息化平台,这是在运维层面的称,运维层面之上有我们的基础服务,包括短域名,包括整个的沟通,因为用户卖家和买家的沟通,包括我们的push服务。还有技术组件,数据库的中间件,这些东西需要我们自己打造,当然上面还有一些平台,这些平台主要是为了整个服务来做的,比如说监控去做,你的服务做,你的日志的跟踪去做?当然还有离线任务,你的调度去做,保证你的调度的稳定性。当然我们还有自己的存储层,主要三部分。最上面就是大家说的,我们要做微服务,必然要解决微服务框架的问题,包括你的RPC怎么去做?你的网关怎么去做?好在我们其实没有用业界开源的东西,但是我们的RPC是我们自己打造的,基本上业界听说过的doble和PRC比较类似,所以我们自己做,我们做的东西比较多。我会挑一两个比较重要的跟大家讲一下。

  按照业务模式来做微服务框架

  其实锁这个东西有很多的场景我们可以用到,比如说在整个的交易,因为二手交易平台和新品不一样的地方在哪儿?新品是有库存的概念,但是二手交易平台是没有库存的概念,所有的商品理论上只有一件,所以在这种情况下如果两个人同时对一个订单下定单,如果你要不做一个全局唯一的限制,就可能下订单下重了,超卖的情况,这种情况你需要用到锁保证它资源的唯一性。另外一方面消费,我要产生一个消息,丢到MQ里面,你发送消息的时候你是没有办法保证你的密令性的,你的密令性通过消费端保证,你怎么保证你的消息被一个消费掉了,另外一个就不再去消费他,解决你的消费密令性的问题,这时候也会用到一些锁的问题。

  这种情况无非解决的分布式环境下我们的资源唯一写的问题,这个其实很简单,我相信你们有解决的办法。大家都知道,我直接用readis Setnx Timeout搞就行了。但是用这个做有什么问题呢?理论上来说其实你的锁一旦放在redis里面有一个周期,这个锁什么周期你是不靠控制的。我们的目标是解决这些问题,首先的目标解决强一致性。另外一点,你的锁,我希望是有周期的,刚开始申请到5毫秒,我发现5毫秒还不够,我再续5毫秒,但是redis时代这一点是做不到的。你作为一个锁,业务方向接入你,对你的要求,我希望业务方接入你的步骤极简,如果大家做过技术服务也好,哪怕你让业务多写一行代码,业务告诉你我不干,所以这是很麻烦的一个事,你要做这个事情。可视化管理后台和监控这是必须要去做的。

  怎么做呢?很简单,我们采用ETCD来做,在业界经过了整个的验证,它是简单的KV,它的高可用,数据本身是支持持久化的,所以存储采用ETCD来去做,我们怎么去做呢?ETCD本身是高可用的分布式集群,我们希望在客户端打造一个分布式的客户端,一个锁我当然希望在多个模块都可以公平竞争,所以这是我们的出发点。

  你获取这个锁无非两种模式,一个模式是客户端的TTL,另外一个就是服务端TTL,服务端TTL,就是你的锁一旦到期以后来帮你续租,一个客户端帮你续租,另外一个我希望ETCD本身帮我续租。这个模式是比较简单。

  客户端模式比较简单,比如说我有两个用户,一个客户端A,一个客户端B,拿到锁很简单,直接请求ETCD的一个接口就好了,当然它需要传一些东西,比如说你的Key,你的TTL,包括你要写一些东西,包括你的UID,也是你的锁的唯一标识。

  当然,这时候只有一个用户其实能拿到锁,如果A拿到锁,B必然拿不到锁。这时候一旦A过期以后希望续租,客户端模式有一个线程帮他续租,客户端模式需要客户端帮你做续租。

  另外一块是Server模式很简单,他获得锁都一样,只不过你的续租谁来做?当然我希望Server端来去做。我们实际用什么呢?我们实际一定是用我们的服务端模式,因为流程越少,越稳定,你的客户端接入就越稳定。

  业务接入比较简单,JDK7及以上,用Try代码,如果是JDK7以下,拿到锁以后需要用你的relesad接口来做这一块。两个人同时对它申请就OK了。***清理,如果用JDK7以上如果释放掉以后,我们就直接释放掉了,这个比较简单,不花大功夫去讲了。

  引入分布式事务的解决方案

  另外,想跟大家讲一下事务的问题,刚才讲在微服务架构里面因为我们的模块其实会拆分的非常非常多,拆分非常非常多以后,一个请求过来,你会设计多很多的模块,这些模块同时对多个模块进行更改,这时候你怎么能保证你的数据对多个模块要么都成功,要么都成败。在整个的分布式环境下或者微服务架构下适合你的模块其实很多,这时候你可能需要引入一些分布式事务的解决方案。

  要解决分布式事务的解决方案,有没有什么好办法?你要解决分布式事务理论上是一个长事务,你要解决长事务本质上还是要把这个长事务变成一个短事务,短事务其实就是你的本地事务。这样你的分布事务解决一旦出现问题,你的协调的问题。解决分布式事务有很多方式,比如说补偿的方式。当然也可以在异步环境下通过MQ来去做。在异步的环境下怎么通过MQ实现整个分布式的锁,分布式事务来去做这一块,我们的目的最终保证数据一致性。

  怎么做呢?很简单,MQ其实可以提供类似于TCC的分布式的功能,因为我希望通过一个MQ的事务消息解决我的数据最终一致性的问题,什么叫业务场景,刚才讲我们是使用在一些异步的场景去做,我们现在在一个交易环境下下单的支付,我希望下单成功以后产生一个消息放在MQ里面,这时候支付环节从MQ里面读从消息里面异步进行处理,这个环节是异步场景,关键怎么保证下单能成功?我在下单能成功,把下单以后的消息放在MQ里面企事业能成功。如果使用正常的MQ,下单之前首先放一个消息在MQ里面,可不可以?也是可以的,但是有可能把消息放在MQ之后,你真正下单失败了,这时候你放的消息就没用了,也可以选择我先下单,下单成功之后再把这个消息放在MQ里面,但是也有可能你把这个消息放在MQ里面又失败了,因为它是两步操作,你都没有办法保证它一致性的问题,这是头痛的问题,我们希望我的下单和产生消息在异步环境下,的确有可能把它放在MQ里面失败了,但是失败以后,我希望业务方能够提供一个回查的借口,我再去回查,你告诉我成功与否,如果成功了,我再去做这一块。

  这个思路很简单,我们希望我的业务方能提一个本地操作的回查接口,涉及两个状态,一个叫半消息,一个叫消息的回查。这个图是一个流动图,MQ发送方就是MQ的客户端,本地性的事务就是下单。我们做这个事呢?***步做下单操作之前做一个什么事儿呢?首先向MQ服务事务端里面发送一个半消息,这时候发到MQ里面是不会被下游性的,MQ受到这个成功消息之后,知道这个半消息已经发到MQ了,业务方可以做什么事呢?第三步就可以执行下单的本地事务。一旦我的下单本地事务执行成功。

  第四步,如果成功了我就再提交一个消息,告诉我的MQ,我的整个本地事务已经执行完了,这个时候可以把刚才这个消息投递给你的消费方,顺利的情况下MQ告诉你的发送方,我也收到这个消息,就OK了,有可能你发送这个消息的时候由于网络的异常,你的发送方其实没有收到,这时候很简单,大家看第五步,如果这时候我的MQ发送方没有收到你发给MQ的消息,这时候很简单,你的发送方检查你的本地事务,这时候刚才操作有没有成功?假设你查出你的本地事务发现这个订单我其实已经下过了,这时候你会做一个什么事情?很显然第七部,根据我的事务做reback,通过这种方式,总能保证最终这个消息是成功被消费的,野鸽方案理论上是OK的,它的优点比较通用,它的缺点是你的业务方需要提供一个回查的接口,你每做一个本地事务,你需要把本地事务的回查接口提供给你的MQ发送方让他查询,也是对业务方是有代价的,当然过程不用讲了。

  第四步执行本地的操作,OK以后,你提交,这时候对你的发送方来说,其实你需要去提交或者去回滚这个brouk。他的***问题不在于提交,问题每次做这样一个事务以后,我的业务方都要提供一个回查的接口,这个其实很多情况下对于你的业务方是不愿意干的。这个方案本身是没有问题的。我们能不能有一个方案能完成我们对重设计的一致性,有可能。我们期望做什么事情呢?我们希望说,刚才说我的下单和我产生一个MQ消息这两步操作,我们能不能做这件事情?我把我本地的下单和我产生消息,这时候我不是直接放在MQ里面,我能不能直接通过本地事务的方式把下单操作和产生消息的操作放在一个里面,如果能放在一个里面,那么你的订单和你的下单,你的订单和产生消息,要么都成,要么都失败就OK了,这时候你还需要多一个从你本地的消息表里面读出消息传到你的MQ里面就好了。如果这样的话,业务方其实不需要提供回查接口的,这样会比较爽一点。

  所以很简单,去做也一块呢?我们希望在用户做本地操作事务表的同时,我们给他放一张本地的消息表,开启一个本地事务来做这一块。这是流程。这个流程,这个就是你的微服务的客户端,这就是你的微服务的数据库。

  和此前不一样的地方是什么呢?***步写入业务数据和服务数据,***步在这里面放一个,在这个里面可以对它进行事务的操作,***步一旦成功或者失败,比如说成功了做什么事情呢?从事务表里面读出来本地事务放到我们的MQ里面去。所以第三步,读出来以后,我的微服务可以把这个协议再写到MQ里面,同时MQ给你的微服务和客户端,我就可以去做这个事情,这是需要你的MQ的客户端多做一些事情,同你刚才提交的本地的消息表里面读出来,再放在本地。所以这是这个方式。

  我们最终选择的是这种方式,因为时间有限,其他的东西没有办法给大家展开,有兴趣的时候我们可以交流一下。这个基本上是我今天讲的内容。其他的我们采用的本地事务消息表去做这一块。

  讲完这个今天我的分享就结束了,主要是带领大家去学习了一下整个微服务架构设计的一些理念,以及我们整个云事务,给大家举了两个例子,以及锁和整个事务怎么去做。

责任编辑:张诚 来源: 51CTO
相关推荐

2016-08-11 22:32:27

2018-06-14 15:09:23

转转AI工程架构体系

2018-04-25 10:05:09

AI微服务架构算法

2016-10-26 18:02:54

高可用性系统服务器

2010-08-03 16:45:57

VMware财富证券实时在线交易平台

2020-05-06 15:48:24

Python数据二手房价

2020-06-05 19:19:03

苹果促销商家

2011-04-29 14:35:53

惠普工作站

2010-04-29 16:22:39

Juniper交易平台

2018-10-29 15:41:16

二手硬件处理器

2017-11-06 13:39:20

大数据隐私个人信息

2012-06-25 16:59:16

2014-08-19 09:34:01

2012-10-23 14:08:49

白忙活的体验

2014-11-17 11:19:37

2023-04-13 10:12:07

交易平台架构

2016-10-28 09:37:48

微服务架构服务

2023-02-08 09:42:30

策略方式容量

2017-11-13 18:25:35

点赞
收藏

51CTO技术栈公众号