`
uule
  • 浏览: 6352378 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

关于大型网站技术演进的思考(二)--存储的瓶颈(3)*

 
阅读更多

来源:夏天的森林

 

拆分后的查询

垂直拆分导致的分布式事务问题 

 

存储的瓶颈写到现在就要进入到深水区了,如果我们所做的网站已经到了做数据库垂直拆分和水平拆分的阶段,那么此时我们所面临的技术难度的挑战也会大大增强。

  这里我们先回顾下数据库的垂直拆分和水平拆分的定义:

  垂直拆分:把一个数据库中不同业务单元的数据分到不同的数据库里。按功能

  水平拆分:是根据一定的规则把同一业务单元的数据拆分到多个数据库里。按数据

  垂直拆分是一个粗粒度的拆分数据,它主要是将原来在一个数据库下的表拆分到不同的数据库里水平拆分粒度比垂直拆分要更细点,它是将一张表拆到不同数据库里,粒度的粗细也会导致实现技术的难度的也不一样,很明显水平拆分的技术难度要远大于垂直拆分的技术难度。难度意味着投入的成本的增加以及我们需要承担的风险的加大,我们做系统开发一定要有个清晰的认识:能用简单的方案解决问题,就一定要毫不犹豫的舍弃复杂的方案,当系统需要使用高难度技术的时候,我们一定要让自己感受到这是迫不得已的

  我是以java工程师应聘进了我现在的公司,所以在我转到专职前端前,我也做过不少java的应用开发,当时我在公司的前辈告诉我,我们公司的数据库建模很简单,怎么个简单法了,数据库的表之间都没有外键,数据库不准写触发器,可以写写存储过程,但是存储过程决不能用于处理生产业务逻辑,而只能是一些辅助工作,例如导入导出写数据啊,后面听说就算是数据库做到了读写分离,数据之间同步也最好是用java程序做,也不要使用存储过程,除非迫不得已。开始我还不太理解这些做法,这种不理解不是指我质疑了公司的做法,而是我在想如果一个数据库我们就用了这么一点功能,那还不如让数据库公司为咋们定制个阉割版算了,不过在我学习了hadoop之后我有点理解这个背后的深意了,其实作为存储数据的数据库,它和我们开发出的程序的本质是一样的那就是:存储和计算,那么当数据库作为一个业务系统的存储介质时候,那么它的存储对业务系统的重要性要远远大于它所能承担的计算功能,当数据库作为互联网系统的存储介质时候,如果这个互联网系统成长迅速,那么这个时候我们对数据库存储的要求就会越来越高,最后估计我们都想把数据库的计算特性给阉割掉,当然数据库基本的增删改查我们是不能舍弃的,因为它们是数据库和外界沟通的入口,我们如果接触过具有海量数据的数据库,我们会发现让数据库运行的单个sql语句都会变得异常简洁和简单,因为这个时候我们知道数据库已经在存储这块承担了太多的负担,那么我们能帮助数据库的手段只能是尽量降低它运算的压力

  回到关于数据库垂直拆分和水平拆分的问题,假如我们的数据库设计按照我们公司业务数据库为蓝本的话,那么数据库进行了水平拆分我们会碰到什么样的问题了?为了回答这个问题我就要比较下拆分前和拆分后会给调用数据库的程序带来怎样的不同,不同主要是两点:

  第一点:被拆出的表和原库的其他表有关联查询即使用join查询的操作需要进行改变;

  第二点:某些增删改(注意:一般业务库设计很少使用物理删除,因为这个操作十分危险,这里的删往往是逻辑删除,一般做法就是更新下记录的状态,本质是一个更新操作)牵涉到拆分的表和原库其他表共同完成,那么该操作的事务性就会被打破,如果处理不好,假如碰到操作失败,业务无法做到回滚,这会对业务操作的安全性带来极大的风险。

 

  关于解决第一点的问题还是相对比较简单的,方式方法也很多,下面我来讲讲我所知道的一些方法,具体如下:

  方法一:在垂直拆表时候,我们先梳理下使用到join操作sql查询,梳理的维度是以被拆分出的表为原点,如果是弱依赖的join表我们改写下sql查询语句,如果是强依赖的join表则随拆分表一起拆分,这个方法很简单也很可控,但是这个技术方案存在一个问题,就是让拆分粒度变大,拆分的业务规则被干扰,这么拆分很容易犯一个问题就是一个数据库里总会存在这样一些表,就是很多数据库都会和它关联,我们很难拆解这些关联关系,当我们无法理清时候就会把该表做冗余,即不同数据库存在雷同表,随着业务增长,这种表的数据同步就成为了数据库的一个软肋,最终它会演变为整个数据库系统的短板甚至是全系统的短板。

  方法二:我们拆表的准则还是按业务按需求在数据库层面进行,等数据库拆好后,再改写原来受到影响的join查询语句,这里我要说明的是查询语句修改的成本很低,因为查询操作是个只读操作,它不会改变任何底层的东西,如果数据表跨库,我们可以把join查询拆分为多次查询,最后将查询结果在内存中归纳和合并,其实我们如果主动拆库,绝不会把换个不同的数据库产品建立新库,肯定是使用相同数据库,同类型的数据库基本都支持跨库查询,不过跨库查询听说效率不咋地,我们可以有选择的使用。这种方案也有个致命的缺点,我们做数据库垂直拆分绝不可能一次到位,一般都是多次迭代,而该方案的影响面很大,关联方过多,每次拆表几乎要检查所有相关的sql语句,这会导致系统不断累积不可预知的风险。

  以下三段内容是方法三:

      不管是方法一还是方法二,都有一个很根本的缺陷就是数据库和上层业务操作耦合度很高,每次数据库的变迁都导致业务开发跟随做大量的同步工作,这样的后果就是资源浪费,做服务的人不能天天被数据库牵着鼻子走,这样业务系统的日常维护和业务扩展会很存问题,那么我们一定要有一个服务和数据库解耦方案,那么这里我们就得借鉴ORM技术了。(这里我要说明下,方法一和方法二我都是以修改sql阐述的,在现实开发里很多系统会使用ORM技术,互联网一般用ibatis和mybatis这种半ORM的产品,因为它们可以直接写sql和数据库最为亲近,如果使用hibernate则就不同了,但是hibernate虽然大部分不是直接写sql,但是它只不过是对数据库操作做了一层映射,本质手段是一致,所以上文的sql可以算是一种指代,它也包括ORM里的映射技术)

       传统的ORM技术例如hibernate还有mybatis都是针对单库进行的,并不能帮我们解决垂直拆分的问题,因此我们必须自己开发一套解决跨库操作的ORM系统,这里我只针对查询的ORM谈谈自己的看法(讲到这里是不是有些人会有种似成相识的感觉,这个不是和分布式系统很像吗)。

       其实具体怎么重构有问题的sql不是我想讨论的问题,因为这是个技术手段或者说是一个技术上的技巧问题,我这里重点讲讲这个ORM与服务层接口的交互,对于服务层而言,服务层最怕的就是被数据库牵着鼻子走,因为当数据库要进行重大改变时候,服务层总是想方设法让自己不要发生变化,对于数据库层而言服务层的建议都应该是合理,数据库层要把服务层当做自己的需求方,这样双方才能齐心协力完成这件重要的工作,那么服务层一般是怎样和数据库层交互的呢?

       从传统的ORM技术我们可以找到答案,具体的方式有两种:

       第一种:以hibernate为代表的,hibernate框架有一套自己的查询语言就是hql,它类似于sql,自定义一套查询语言看起来很酷,也非常灵活,但是实现难度非常之高,因为这种做法相当于我们要自己编写一套新的编程语言,如果这个语言设计不好,使用者又理解不深入,最后往往会事与愿违,就像hibernate的hql,我们经常令可直接使用sql也不愿意使用hql,这其中的缘由用过的人一定很好理解的。

      第二种就是数据层给服务层提供调用方法,每个方法对应一个具体的数据库操作,就算底层数据库发生重大变迁,只要提供给服务端的方法定义不变,那么数据库的变迁对服务层影响度也会最低。

      前面我提到技术难度是我们选择技术的一个重要指标,相比之下第二种方案将会是我们的首选。

 

      垂直拆分数据库还会带来另一个问题就是对事务的影响垂直拆分数据库会导致原来的事务机制变成了分布式事务,解决分布式事务问题是非常难的,特别是如果我们想使用业界推出的解决分布式事务方案,那么要自己实现个分布式事务就更难了,不过这里我要说明一下,我这里说的更难是和我写本文有关,我本篇文章之所以现在才写是因为我想先研究下业界推出的分布式解决方案,但是这些方案的原理看得我很沮丧,我就想如果我们直接用方案的接口实现了它,因为还是不懂他的很多原理,那么这些方案其实就是不可控方案,说不定使用过多就会给系统埋下定时咋但,因此这里我就只提提这些方案,有兴趣的童鞋可以去研究下:

  一、X/OPEN组织推出的分布式事务规范XA,其中还包括该组织定义的分布式事务处理模型X/OPEN

  二、大型网站一致性理论CAP/BASE

  三、 PAXOS协议。

  这里特别要提的是PAXOS协议,我以前写过好几篇关于zookeeper的文章,zookeeper框架有一个特性就是它本身是一个分布式文件系统,当我们往zookeeper写数据时候,zookeeper集群能保证我们的写操作的可靠性,这个可靠性和我们使用线程安全来控制写数据一样,绝对不会让写操作出错,之所以zookeeper能做到这点,是因为zookeeper内部有一个类似PAXOS协议的协议,这个协议类似一个选举方案,它能保证写入操作的原子性。

  其实事务也是和线程安全技术类似,只不过事务是要保证一个业务操作的原子性问题,当然事务还要有个特点就是回滚机制即业务操作失败,事务可以保证系统恢复到业务操作前的状态,回滚机制的本质其实是维护业务操作的状态性,具体点我这里列举个例子:当系统将要执行一个业务操作时候,我们首先为业务系统定义一个初始状态,业务执行操作时候我们可以定义一个执行状态,操作成功就是一个成功状态,操作失败就是一个操作失败状态,如果业务操作是失败状态,我们可以让业务回滚到初始状态,更进一步如果执行状态超时也可以将整个业务状态回退到初始状态,其实所有事务回滚机制的本质基本都是如此。记得不久前,在群里有个群友就问大家如何实现分布式事务,他想要知道的分布式事务是有没有一种技术能像我们操作数据库或者是jdbc那样一个commit,一个rollback就搞定,但是现实中的分布式事务比commit和rollback复杂的多,不可能简单的让我们写几个标记就能实现分布式事务,当然业界是有方案的,就是我上面提到的,如果有人真想知道可以自己研究下,不过我本人现在还是不太懂上面这些技术的原理和思想。

  其实当时我马上给那位群友一个解答,我说我们开发时候是经常碰到分布式事务,但是我们解决分布式事务大多数从业务角度来解决的,而没去选择纯技术手段,因为技术手段太复杂难以控制。这个答案可能不会令提问者满意,但是我现在还是坚持这个观点,这个观点符合我提到的原则,当技术方案难度过高,我们就不要轻易选择使用它,因为这么做是很危险的,今天我就举个例子吧,这样可能更有说服力。我现在做的系统很多业务操作经常要和其他系统共同完成,其他系统有我们公司自己的系统,也有其他企业的系统,这里我还是把业务操作比作一辆在高速公路的汽车,那么每个系统就是高速公路上的一个收费站,业务每到一个收费站,该系统的数据库就会在对应的数据库的某张表里某条记录上记录一个状态,当汽车跑完全程,各个收费站就会相互通知,告诉大家任务完成,最终将所有的状态置为已完成,如果失败,就废掉这辆汽车,收费站之间也会相互通知,让所有的记录状态回归到初始状态,就当从来没有这辆汽车来过。这个做法的原理就是使用了事务回滚的本质,状态的变迁和回退,这个做法在业务系统开发里也有个专有术语就是工作流。其实大多数问如何实现分布式事务如何实现的问题的本质就是想解决事务的回滚问题,我们其实不要被这个分布式事务的名字给吓住了,其实有很多不起眼的技术手段和业务手段都能达到相同的目的。

  晚上11点了,看来本文今天写不完了,今天就到此为止,最后我要总结下本文的内容,具体如下:

  1. 大型网站解决存储瓶颈的问题,我们要找准存储这个关键点,因为数据库其实是存储和运算的组合体,但是在我们这个场景下,存储是第一位的,当存储是瓶颈时候我们要狠下心来尽量多的抛弃数据的计算特点,所以上文中我提出我们数据库就不要滥用计算功能了例如触发器、存储过程等等。

  2. 数据库剥离计算功能不代表不要数据的计算功能,因为没有数据的计算功能数据库也就没价值了,那么我们要将数据库的计算功能进行迁移,迁移到程序里面,一般大型系统程序和数据库都是分开部署到不同服务器上,因此程序里处理数据计算就不会影响到数据库所在服务器的性能,就可以让安装数据库的服务器专心服务于存储。

  3. 我们要尽一切可能的把数据库的变化对服务层的影响降到最低,最好是数据库做拆分后,现有业务不要任何的更改,那么我们就得设计一个全新的数据访问层,这个数据访问层将数据库和服务层进行解耦,任何数据库的变化都由数据访问层消化,数据访问层对外接口要高度统一,不要轻易改变。

  4. 如果我们设计了数据访问层来解决数据库拆分的问题,数据访问层加上数据库其实就组合出了一个分布式数据库的解决方案,由此可见拆分数据库的难度是很高的,因为数据库将拥有分布式的特性,而分布式开发就意味开发难度的增加。

  5. 对于分布式事务的处理,我们尽量要从具体问题具体分析,不要一感觉这个事务操作本质是分布式事务就去寻找通用的分布式事务技术手段,这样的想法其实是回避困难的思想,结果可能会是把问题搞得更加复杂。

分享到:
评论

相关推荐

    菜鸟数据中台技术演进之路-陈飞.pdf

    根据给定文件的信息,我们可以提炼出一系列与APT(Advanced Persistent Threat,高级持续性威胁)攻击相关的技术知识点。这些知识点覆盖了APT攻击从准备到实施再到后续行动的各个环节,旨在为读者提供一个全面深入的...

    从大型电商架构演进看互联网高可用架构设计——内训方案.pdf

    #### 二、大型电商系统架构演进分析及背后的思考 **京东电商系统架构演进** 1. **V1.0架构**:单体架构为主,简单直接但难以应对快速增长的业务需求。 2. **V2.0架构**:引入分层架构和部分微服务架构,提高了系统...

    携程技术演进之路-携程李小林.pdf

    ### 携程技术演进之路 #### 一、携程技术演进背景及历程 携程作为中国领先的在线旅行服务公司,其技术体系经历了从呼叫中心时代到互联网与移动互联网时代的转变,再到现今的大数据与人工智能时代的演进。这一过程...

    C-V2X业务演进白皮书-完整版.pdf

    ### C-V2X业务演进的关键知识点 #### 1. C-V2X业务演进趋势 **背景介绍:** C-V2X(Cellular Vehicle-to-Everything)是一种基于蜂窝网络技术实现车辆与一切(包括车辆、行人、路侧单元等)之间通信的技术。随着5G...

    数据中台演进实施方案-四川电信-v.qy.pptx

    ### 数据中台演进实施方案-四川电信-v.qy.pptx #### 一、概述 在当前数字化转型的大背景下,企业对于数据驱动的需求日益增长。四川电信为了更好地利用其丰富的数据资源,提出了“数据中台演进实施方案”。该方案...

    3GPP长期演进(LTE)技术原理与系统设计

    ### 3GPP长期演进(LTE)技术原理与系统设计 #### 一、LTE产生的背景及重要技术特点 **1.1 LTE产生的背景** 随着移动互联网的快速发展,人们对高速数据传输的需求日益增长,传统的3G网络已无法满足这一需求。在此...

    电力设备新能源2023年投资策略:产业链博弈要素转换,新技术加速演进-202212-浙商证券-75页.pdf

    - **钨丝金刚线、银浆等环节受益于新技术迭代**:随着光伏技术的进步,钨丝金刚线、银浆等辅材也将迎来技术升级的机会,从而提升整体产业链的技术水平。 - **微型逆变器及储能逆变器维持高增长**:随着分布式光伏...

    LTE的关键技术及其标准演进

    **LTE(Long-Term Evolution)是4G移动通信技术的重要组成部分,它在3G网络的基础上实现了显著的速度提升和更低的延迟。本篇文章将深入探讨LTE的关键技术及其标准演进过程,帮助读者理解这一核心技术的原理与特点。*...

    《大型网站技术架构演进与性能优化》

    《大型网站技术架构演进与性能优化》这本书深入探讨了互联网行业中大型网站在技术架构上的发展路径和性能优化策略。随着互联网的飞速发展,大型网站的架构设计和性能优化成为了决定企业竞争力的关键因素。本篇文章将...

    Nutanix-圣经-原厂资料

    #### 一、历史回顾与数据中心的演进 **1.1 数据中心的革命** - **1.1.1 大型机的时代** - 在信息技术发展的早期阶段,大型机是计算能力的核心。这些庞大的计算机系统占据了整个房间,并且需要专门的技术人员来...

    风能储存技术.pdf

    ### 风能储存技术概览 #### 一、引言 随着可再生能源技术的不断发展,尤其是风能和光伏技术的日益成熟,能源储存技术变得...随着技术的进步和市场需求的变化,风能储存技术将继续演进,为可持续能源的发展做出贡献。

    射频和无线技术入门(第二版)

    - **发展**: 从1G到5G的技术演进。 - **关键技术**: GSM、UMTS、LTE、NR等。 #### 四、现代无线通信技术 **4.1 宽带固定无线通信** - **定义**: 提供高速互联网接入服务。 - **技术**: MMDS、LMDS等。 **4.2 ...

    Oracle 笔记.docx

    - **数据的储存方法**: - 大脑记忆:适合少量数据。 - 写在纸上:适用于手动记录,但难以管理和查找。 - 计算机内存:快速访问但易丢失。 - 磁盘文件:持久存储,但检索效率低。 - **数据库的作用**: - 存储...

    AS深圳2018-《超大规模软件架构度量与演进的思考和实践》-吴文胜.pdf

    ### 超大规模软件架构自动化度量与演进的思考和实践 #### 缘起:为何启动架构自动化度量与演进? 随着软件系统规模的不断增大,传统的软件开发模式和架构管理方式面临着前所未有的挑战。例如,在华为这样的大型...

    系统架构演进探析

    #### 二、架构演进过程 随着信息技术的发展,软件架构也经历了从简单到复杂的演变过程。以下是一些关键阶段: 1. **诞生之初 - ALL IN ONE** - **特征**:所有的应用程序、数据库和文件等资源都被部署在同一台...

    分布式 KV 存储系统 Cellar 演进之路--美团.pdf

    ### 分布式KV存储系统Cellar演进之路 #### Cellar起源 Cellar作为一个分布式键值(Key-Value, KV)存储系统,最初起源于美团在2014年初引入阿里巴巴的Tair作为NoSQL存储解决方案的过程。随着业务的发展,Tair在美团...

    藏经阁-饿了么服务架构演进.pdf

    【藏经阁-饿了么服务架构演进.pdf】这篇文档主要讲述了饿了么作为一家外卖服务平台,在面对高并发、瞬时冲击等技术挑战时,如何进行服务化架构的演进,以提升系统稳定性和效率。以下是根据文档内容提炼出的关键知识...

Global site tag (gtag.js) - Google Analytics