首页 > 数据库 > MySQL > 正文

麦包包简朝阳:MySQL的B2C电商系统前端数据层架构

2024-07-24 12:40:13
字体:
来源:转载
供稿:网友

在此次活动中,来自麦包包技术保障部总监简朝阳发表了《MySQL的B2C电商系统前端数据层架构》演讲,在此次演讲中,他带来了三方面的技术分享,一个是基于MySQL常见一些高可用可扩展架构分析;另一方面是基于日志解析对现在一些数据库常见架构方面一些扩展,包括一些可靠性或者高可用性以及一些问题解决方面的内容;再有就是基于用户行为分析系统的一个数据层的构建。 

麦包包技术保障部总监简朝阳

 

以下是简朝阳的演讲实录:

大家好,我是来自麦包包技术保障部的简朝阳,今天我分享的主题是基于MySQL的B2C电商系统前端数据层架构。我之前在互联网企业工作,也是与电子商务相关。之前我自己写过一本MySQL方面的书,可能有些同学看过。

今天主题主要有三个方面,一个是基于MySQL常见一些高可用可扩展架构分析;还有是基于日志解析对现在一些数据库常见架构方面一些扩展,包括一些可靠性或者高可用性,包括一些问题解决方面的内容;最后就是基于用户行为分析这样一个系统的一个数据层的构建。

基于MySQL常见一些高可用可扩展架构分析

常见架构在高可用方面有硬件高可用和数据高可用,因为是数据库、数据层这块,硬件给我们支持数据,数据怎么保护它,怎么让它保护我们的业务正常运行,这两块是重要的。冗余基本上无外乎增加一些备份、备用设备,再一个存储设备的备份,电源的双电源等等这方面的内容,可能这个应该不需要太多的深入讨论,因为这个是比较熟悉的。熟悉高可用可能是我们更关注或者说对大家更有用。数据高可用通过两种方式,一个是共享方式解决,同一份数据被多个主机挂载,这是一个共享的方式。还有就是冗余,多种数据的方式。比如我们通过自己实现或者是第三方实现的数据的程序,这里是数据同步方面的东西,数据多重拷贝来进行多方面访问。这个数据出现问题了,还有其他的数据来保证业务持续下去。

看看共享方面,这是我画的一个架构图,共享的话底层我们的Storages而是一份数据或者是有可能是几份数据,通过中间的交换设备,比如说我们的同构网络,SaaS,通过这样的协议来交换主机。主机可能是一两个节点或者是多个节点承接这个数据,数据做任何变化的时候都是被前端这些节点同时操作,通过底层协议相关的关系来达到我们这个数据的高可用。比如我前端这个节点,数据库或者说我其他的存储设备主机节点出现问题,我数据只要在,我马上可以启用备用节点使用这个数据,不会有任何中断。这是目前比较常见的数据共享这种方式,这是我们今天所要讨论的MySQL。

MySQL的高可用架构是大家比较了解的数据复制的方式,也是目前在整个业界使用MySQL最多的一种保证它的高可用、扩展的一个方式。MySQL数据库的复制跟其他的数据库有点不一样,他是基于逻辑复制,不是独立一个个数据库拷贝,他是从日志里面解析出来,而不是说我主节点有什么数据块的变化再复制到背景里面去。所以MySQL在这个过程中没有主机的限制和协议的限制,这给我们MySQL的利用过程中带来很大的灵活性。

我这里画了一个基本常用的架构图,是双的主节点相互护持,还有三个备节点,可能还有多个节点。我的两个写入节点已经是高可用了,一个节点出现问题,另外一个节点马上可以启用。我们可以通过第三方,比如说类似开源的HA管理人员管理我们的数据库、网络、资源,这里面一个节点任何一个方面,比如网络、数据库出现问题之后,他马上可以通过浮动IP切换,使用另外一个节点提供服务,很好的保证了我们前端写入节点高可用。项目使用,如果使用共享存储或者说共享设备的方式,存在的一个问题就是你的存储数据在提供服务的时候,你只是被一个点去锁住,一旦要切换,你首先遇到一个问题就是必须在主机端要解这个锁,释放这个资源。然后再加锁,再使用这个资源,这个过程很长,如果遇到任何问题就会卡住,HA切换就会遇到问题。但是这种非共享被复制的方式高可用就不会遇到这个问题。因为他的数据是不会加这个锁,数据可以随便写的。所以这共享设备的HA切换,一般消耗的切换时间都需要比通过冗余方式来切换时间要长,你出现故障要切换的时候,碰到冗余的方式就是几秒钟一切换就完了。但是如果你使用共享设备,如果你底层一些存储量比较大,可能要花比较多的时间才会切换完。几秒钟和几分钟对我们的客户来说是有很大的差距的,所以在高可用这一块,可能再通过冗余方式远远好于通过共享的方式。当然冗余方式也会有副作用,比如说管理性,设备利用率方面可能会没有我们共享方式高。但是所带来的价值就是他的操作更灵活,他的可用性更高。他对设备的要求也会更低一些。

当我这样一个架构遇到异常的时候,他如何来改动我们的可能性,首先我们的一个节点出现问题以后,本来我们前面有三个节点,当出现问题之后,看这个箭头,可以把出现问题的节点断掉,剩下好的节点,他们两个资源之间没有一个锁或者是一个资源等待的关系,一旦出现问题他可以非常迅速反映,马上把这个节点弃用,而用其他的节点。所以当我们复制节点出现问题的时候,很容易切换,无论是自己实现这样管理的作业层还是通过其他的软件判断,检查也好都可以做到这个切换。

如果我们的写入节点有问题怎么办?我们看看当我们的A出现问题,会出现什么状况?比如我们太多写A这个节点,当这个节点出现问题的时候,我们所有的业务都可以正常运转,所有客户访问不涉及写入是没有任何异常的。只有在需要写入操作的时候才需要设计这个异常所做出的判断,这个还有B节点,还可以提供服务。可以通过一些脚本、商业软件都可以,主要一些开源软件已经很成熟了,帮助我们管理这些浮动的资源,通过这样浮动IP去判断我们数据库或者是其他的网络是否是通的,数据库资源是否正常。这时候如果我们马上切换到B节点,整个链路没有任何问题,不需要做任何数据库层的切换,只需要IP切换一下,这个过程也是非常短的。

但是可能有些同学会想到,如果我的B节点出现问题怎么办,我们来看一看。正常我们的数据可能写入了A节点,通过B节点复制到后面的三个点。这种情况下B节点做了两个事情,一个是A节点的高可用保证,一个冗余。同时他还做了一个复制的踪迹,两层的复制。这个时候如果B节点出现问题,之前A节点的复制实际上是会中断的。这个中断它的影响其实并不是特别大,因为在这个中断之后对我们业务正常访问读取的话,他的影响只是说我后面读取出来的数据是有一点延迟。我的页面能够让用户看到和不能让用户看到是很大差异,不管数据有没有延迟,如果只是一点故障,整个系统不可见了,让用户看到我们的数据有点延迟,这两种概念是很大差异的。所以这种情况下,对故障的恢复时间也是有很大一个缓冲余地。这种情况下,我们所需要做的就是后面的所有节点从Marste(音)切换到A这个节点,这个时候我们一旦把他的Marste节点从B切换到A之后,之前延迟的数据马上可以恢复赶上去。这个时候如果B节点起来之后,只要数据没有损坏,不是存储数据硬件损坏的话,把硬件更换之后不用做任何操作,不用搭建复制页面,他会自动把数据复制过去。这种情况下,他的影响也是比较小的。一般情况下B节点没有提供任何服务,负载很低,他出现问题的可能性远低于其他的节点,压力大的时候比压力小的时候更会出现问题,大家也会有亲身经历。这是我介绍了一下目前比较常规的一些高可用方面的一些架构。

基于日志解析的准实时同步对架构进行扩展

我们看看我们常规的扩展方向,扩展的话无非两方面,一种是向上扩展,还有一种是向外扩展,向上扩展什么意思呢?就是我们主机或者说里面某些部件升级或者是主机型号升级,或者说我增加一点内存,增加一点硬盘的方式。同样在节点数量方面也增加,只是把这个节点的处理能力增加了。向外扩展是在节点数上面的扩展,就相当于我们常说的储存扩展。他无论是水平拆分还是纵向拆分,增加这个节点数的方式。或者是按模块按功能做一些拆分或者是把同样相关的数据做拆分。前期的话这种纵向扩展维护性方面或者是扩展成本方面比较小,但是达到一定程度之后垂直扩展无法满足要求。我们为了做纵向扩展,从PC机升级到小型机,这个时候小型机非常的昂贵,你一旦上了小型机的船,很难从上面下来,现在小型机厂商也不多,很容易被一个厂商绑架,成本会飞快的飙升。然后向外扩展还有就是复制,这也是向外扩展的一个方式。再一个通过Cache/Search扩展。也是一个扩展的方式。

第一步要做一个纵向扩展,按照模块或者是表把它拆开,然后当一个还不够的时候,某一个模块都没办法通过,我们不得不考虑这种水平扩展,做水平的拆分。这里举的例子,比如我们一些用户信息,用户信息访问。或者是根据产品的ID的方式,水平分拆就是怎么样选择分拆线,这个选择很多时候让我们后面的应用如何去开发会影响很大。一个不太好的分拆线会不知道怎么去应用,因为拆开之后就很难合并,把这些数据拿到一起合并升级其实成本也很高。很多时候我们遇到就是如何选择这个分拆线。我先做了垂直拆分,不满足要求每个地区进行水平拆分。这是我们常见做扩展的方案。也是目前很多电商或者说很多互联网企业在使用的。我们后面是想在常规方案基础上再加入我们的B2C电子商务企业特点,来应对特点来做一些加工扩展和改进。

我们B2C网站的特点我这里列举了几个,不一定完全囊括。我们产品数量的基数并不大,一个企业所卖的东西不像一个平台那么多。而且每一个产品的数据其实变更,产品并行之后它需要变更的内容很少,SKU数量基数不会太大,一般不会超过千万级别。另外一个就是虽然我的SKU的量不多,但是每一个SKU被访问到的次数很大,我的基数少,但是访问量高,我的次数平均被访问是很大的。而且网上购物什么的,大家可能平时都在上班,我购物的时候是很集中的,不像有些网站,新闻网站上班可以看看,波峰和波谷时间差异不是特别大。电子商务和购物在平时来看很多网站对我们B2C来说可能是高峰,下班这个时间可能就是高峰或者是很晚的时候还是高峰。

另外我们的数据少,但是他访问多,数据比起来少,整体来说这差异很大。另外一个,我们是针对和消费者做很多分析服务,包括我们后面还有很多供应链管理、仓储相关,前端系统和后端仓储、物流相关信息交互很多。不像传统互联网企业,你所做的是信息,没有后端传统,这些数据交互,所以这种情况下,以后交互很少,会在这个信息上面去浏览,不会有传统的东西在里面。他这里面有很大的差异,交互很多。

针对这个特点,我们要做什么时期呢?可以把我们写入集中化,写入的量并不是想象那么大,不像平台企业那样有那么多写入。大部分的写入是自己在写入,内部系统在写入。用户的交易性内容可能会写入比较多,但是我们写入会比较少,这时候的写入会做集中化管理,他不会有太大瓶颈,至少在一定范围内可用。但是我们读就不一样,虽然访问用户很多,任何人在下班买东西之前不会看完第一眼就下单,他会不断看,所以浏览次数会很多,读取就会受影响。所以这种读取一定要扩展。而且读取的扩展比别的是方便的,如果我们扩展写入的话里面涉及逻辑,所以数据交互,你读取的时候可以按照模块、各方面MySQL的数据进行拆分,可以减少很多写入的放大。

我们的交易和产品两个分离,交易写入量非常多,需要很长的一致性,它的优化模型不一样,我们的产品分离。为什么要分离?因为产品大部分都是读,而且他的读的量很集中,这样我们可以利用他的MySQL的日志,开放性写的特点,自己做复制。利用MySQL的开放性是怎么样扩展这个系统。很多朋友会问我为什么自己去做开发或者是做复制,或者是利用现成的方案。我们的读在扩展的时候如果你只是做简单复制的方式,你写的每一个点都要复制到读上面。这种复制过程中写入放大是很可怕的。这种冗余或者复制方案只可能解决你读的问题。自己的用户只写了一个点,但是复制到其他点的时候每次只做写入,而且是单线层的写入,当你遇到大篇写入的时候会容易出现延时。虽然他另外一个事物比这个大事物早很长时间完成了,但是他一定要完成之前这个事物,才可能往后面做。我们就可以利用MySQL这种比较开放的复制协议来做一些简单开发。自己来复制我们数据,我只把我需要这个数据复制到相应节点,而不是所有的节点。MySQL基于对数据库的过滤数据,整个数据传输还是一样的。

我们要减少和后端的一些交互节点,减少交互节点是为什么呢?因为我们各种数据交互以及交互的点或者是交互方式越简单,他遇到的问题越少。你这个交互成为一个网状的时候,不知道去管理维护了。

这了发了一个写入集中简单的示意图,我们在一个点写入,通过日志解析,数据复制,再通过我们自己对日志协议的理解,加入一些方式,可以很大程度缓解数据,让延时更少,让复制更灵活。通过这样一种方式去做复制。比如说这里SQU可能分为多个库,这种促销相关信息又分到一个地方去,各种订单也分到一个地方去,还有很多其他的类似的东西。

产品和交易库分离,比如把交易分到一边,产品分到一边,包括扩展方式也有很大差异。交易相关数据,他的一致性要求高,需要事物支持,你一旦涉及到钱这个东西之后,你做了一半结果失败了,客户肯定不愿意了。或者说里面有异常,钱没收回来,你自己肯定也不愿意。这里面一定要出现一个强一致性的。然后交易的量是很大,是一个几何基数方式。交易写入量也很大,不断有相关数据进去出来,所以写入量很大。所以在交易方式,我们一般采用什么方式扩展呢?更多使用是向上扩展。我们增强交易主机的处理能力,增强IO设备的IO能力。你会面临当失败之后如何去往下走的问题,包括你后面补偿也好,这个出现问题后面的会很复杂。为了减少这种,减少节点,就使用独立节点,把这个独立节点能力加强,这种方式无论是维护性还有系统开发方面都会有很大的优势。本身由于这一块你交易是直接你的公司能力相关的。你说他扩展的时候在成本可控的情况下愿意投入这笔钱,毕竟他是这块的核心,而且他涉及的点并不是特别多。所以他扩展也是比较容易解决的。我们产品相关就有另外一个特点,一致性要求没有那么高,操作有时候是单条记录,但个点。数据本身要求也没有那么苛刻,他不需要这种强制性保护,最终一致性就OK,很符合我们分布式做法的。因为他量小,他的基数小,而且他的数据持续性要求不像我们的交易数据那么大,交易数据用户一直操作,不能等他一会刷新之后才可以看到下一步操作,产品不一样。你自己内部一些产品部门或者一些管理部门做一些产品分析之后,他不需要立刻让用户看到,用户延时一块看到实际上影响不大。你这种基于时间点促销,实际上这种活动相关的数据,你是可以提前做一些准备的,不可能我让我的产品人员就等着,我12点要促销,我12点就点这个促销,插入什么东西,肯定要预设的,所以扩展方式也不一样。还有变化小,可以用Cache去解决。再看看我们把后端加进来,后端仓储和物流的交互,不管他可能是直接通过数据库或者是应用交互的时候都在减少中间的交互节点。不要让他去为了节省一点点读取,为写入节点增加一些资源,虽然消耗了节点资源,但是整个复杂性会降低很多。

第三个节点,这里说的是分析推荐系统。我的一个电子商务的企业,我这里说的是必要性。为什么我们需要这样一个系统,首先我们需要根据我们一些访问的数据或者是日志数据,你需要提升用户体验,拿到这些用户分析结果,你平时自己去看自己的网站觉得很好,但是换一个角度,用户角度他是用你这个系统的时候他可能看到是另外一个东西,他更多看到是不好的方面,你更多看到是好的方面,掩盖这些有问题的地方。左翼我们通过这种分析推荐的系统或者是日志的分析系统可以降低这种出现问题之后的难度,提高用户的使用体验。在这个过程中也是提升整体品牌形象的一个很好的方式。

还有一方面,我自己写的是提升销量,这可能是写的比较直接的,我们为什么可以认为能提升销量呢。每个公司不可能每样产品一样的销售情况,有一些是滞销,有一些是热销产品。我们最可能的就是滞销品,出现的原因也很多?有的是产品本身有问题,用户用了觉得不习惯、不大好,不愿意买。还有一种情况,我这个产品,用户根本就是看到的机会比较少,我这里说的曝光率。当这个产品的曝光率没有达到一定量的时候或者是比别人多少的时候,他成了滞销品启示是很自然的事情。我们的系统不一定知道哪个产品的曝光率不够,一定要让我们分析用户的点击行为,分析每个产品的曝光率量,然后提高这种因为曝光而成为只品产品的销量,直接提升我们的整体销量。

然后还有一点,我们可以根据用户的一些使用习惯,可以分析用户一些兴趣点,分析他所喜欢的这些产品到底是什么样的,什么类型的,是什么价位的。这些数据对我们来说都是很有用的,这样我们在查找这个商品或者说他在选商品的时候,我们可以大大缩短他选商品的时间,让他一旦进入我们系统之后,可以找到自己想要什么系统,想要什么样的产品因为我们可以推荐,我们根据他以往一些购买经历,以往一些点击行为的数据进行分析,可以分析出他对那些产品感兴趣,我们增强加大这些产品在他面前的曝光率,做到每个用户进来现实的个性化,还可以增加他们购买得欲望,也是提升我们销量很好的事情。还有其他我这里没有一一列举。

我们这个分析系统好处很多,实际上他也面临很多问题,怎么样实现这个分析系统,怎么样做好这个推荐过程。比如说我们第一个来讲,我基础数据怎么收集,我到底该收集哪些数据,这个问题也是一个难点。最初的时候不知道该收集哪个数据。刚开始随便收集数据,然后慢慢分析,我收集的这个数据量很大,如何过滤没有用的,这也是一个问题。因为你收集很多数据进来,发现你占用空间大,量大,难度大。还有数据范围广,包括自己的产品的属性、归类也是你关系的,这时候可能会影响你在收集的应用,通过PS或者是在应用里面嵌入代码划点等方式,都有可能对我们的系统造成影响。这时候如何降低我们的收集数据的应用对我们原本应用影响也是一个难点,这是一个技术难点。搜集结果也分析,这时候可能存在两方面难点,一个就是结构数据量大,通过传统的关系数据库你很难去处理。你没有很好的常规的日志分析工具去分析,常规日志分析工具就是常规的功能,我们需要远不止这些,我们需要自己设计、定制一些功能,所以没有一个合适的商业软件去满足。这两方面是一个技术的问题,还有就是我们如何制定这个模型,分析的模型,这可能更多是一个数据和商业方面的问题。

我们分析,可能我搭建大型的分布式系统去做,也能解决这个积蓄问题。怎么样把数据分析结果反馈到前端网站,怎么样让用户在网上点,浏览网站的时候提示数据反馈回去,这也是一个问题。你不可能让前端程序直接访问后端的集群,这个分析也会做到实时性。

构建基于用户访问行为的实时推荐分析系统数据层

针对这里几个技术难点,我后面做简单的介绍。因为前面两个纯技术方面的东西和商业方面都有关系,后面这个点基本上就是纯技术方面的东西。看看后面的内容,我们这个分析推荐系统如何组建,如何搭建他。这里设计了一个方案,大家可以看一下。关系型结构化方式将用户行为记录在MySQL数据库中。我通过Blacphole存储引擎作为行为记录的基础表引擎。再把这个数据中转到MySQL它的一个开源仓储解决方案,Infobright。这个过程中我们是利用了实时的解析Binlog方式,将这个数据转发到Infobright里面。这个做的好处就是标准的SQL接口对数据进行访问。无论是前端写数据还是后面分析数据,都可以对SQL接口,降低我们对程序开发成本。为什么会选择这种Blacphole的存储引擎呢,他只是记录日志,真正数据没有记录下来,只是作为一个中转。因为Blackhole作为仓储引擎他的并发量是有限的。虽然他不像很多其他的系统,可是他的并发量会受到很大的限制,他可以由一定的并发,但是不可能做到其他的系统一样提供那样的并发。所以可以降低很多他在并发方面的开销,真正专注于他擅长一点,做分析。

前端用一个MySQL数据库接管这些数据,也是有统一的接口。当他不写数据的时候,他不需要保证这个数据的非常可靠的特性,用我们的日志数据,你丢个几条没有问题,他不像我们的交易数据,他是可以丢的。所以他日志不需要每次都同步到磁盘,这时候基本上数据都还在我们内粗里面,所以性能影响很小。所以我简单做这样一个架构。

我们看后面一些,我画了一个图,我中间这里画了一个是用户数据集群,做了相关分离,每个都是多个节点的数据库,我们的应用陈旭会通过一些各种类型的GS或者是其他的嵌入式的包,把日志写到Blacphole存储引擎,通过日志同步工具,这种分析引擎实时跟应用程序交互,我们把分析结构以异步方式嵌入到前面的应用程序,Web页面程序。这样对我们前端应用影响很小,而且这个分析结构一直在变化。虽然可能每一次展示分析结构,并不是他上一次点击完的分析结构,而是一直跟着他的点击流做分析和变化。

这就是我做的简单的一个架构图,可能没有深入的去分析每一个点。这里我之所以说这样一个架构,我在这里把他列出来,文件节点要统一,可能会出现一些延时等等。扩展能力很强,但是他的并发节点很弱,一个节点他占用80-90%,他的系统能力可能就榨干了整个硬件设备的能力。

这个软件我后面可以介绍他大概的结构情况,MySQL的Infobright是基于存储解决方案的引擎,他有非常好的架构在里面,在下面的知识网格,他在数据进去的时候不断统计你这些数据,运算他的一些分析,每一个状态一些柱状图还有信息。我们常规的数据都是基于行的,但是这个有非常强的压缩能力,他的压缩是比较大的。他还可以支持MySQL原先的运行,Infobright存储引擎,有开源版也有别的版的,大家可以研究一下。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表