eBay Architecture(5)–Partition Everything[Database]

来源:互联网 发布:天庭淘宝城 编辑:程序博客网 时间:2024/05/29 02:32

Randy引用了Eric的一句话,"If you can’t split it, you can’t scale it"。在这里Partition和Split是一个意思,就是把一个大家伙切分成便于管理的小家伙。如果我们做一个项目,里面有一个模块无法Partition,这就意味着一个风险:因为这个模块没有办法Partition,也就是说所有要和该模块打交道的应用都汇聚于一点,如果这个点崩溃了,整个系统就垮了。我们这里所讨论的是系统的横向扩展。如果你没有办法Split,那load高了以后,我们就只能进行纵向扩展,这意味着买更好的机器,更大的内存,更强的CPU…

在进行Partition/Split的时候,我们可以从data,load or usage pattern多个方面来考虑,所以上面那句话完整的因该是:

Split every problem into manageable chunks
        By data, load, and/or usage pattern…

接下来的一个问题就是,如何说服大家Partition Everything的重要性,下面4点就是eBay进行Partition Everything的动机:

Motivations

  1. Scalability: can scale honzontally and independently。到目前为止,我们谈到扩展性的时候都在强调横向扩展。如果我们的设计是能够很方便的进行Partition的话,那剩下的问题就是Partition的粒度而已。这里注意一点,Partition与Partition之间都是独立的。在进行扩展的时候,我们只需要购买更多相同型号的机器而已。
  2. Availability: can isolate failures。Partition避免了单点的bottleneck,从而大大减少了单点崩溃导致系统崩溃的可能性。
  3. Manageability: can decouple different segments and functional areas。由于进行了很好的切分,管理的时候更方便,出了问题也更容易定位。
  4. Cost: can use less expensive hardware。Partition的一大好处就是可以“三个臭皮匠,顶个诸葛亮”,能满足在系统成本和负载的线性关系。如果不这样,单单只是纵向扩展的话,系统的复杂程度和成本往往都是负载的指数函数。

前面我们提到过architect考虑问题的5个方面:Scalability,Availability,Latency,Manageability和Cost。这里在考虑Partition Everything的策略时Randy也是用了同样的分析方法。这里除了Latency,其他4各方面都 cover到了。就Latency来说,我自己的理解是: Partition增加了系统的并发性能,对Latency是有好处的。

既然决定要Partition,那剩下的就是如何进行Partition的问题了。Randy给了两个outline:

  • Functional Segmentation (功能切分)
  • Horizontal Split (横向扩展)

 

[Databases]:Functional Segmentation

1. Segment databases into functional areas.

要支持eBay的业务,不是一两个数据库所能实现的。事实上,eBay拥有超过1000台不同Logical databases部署在大约400台物理数据库服务器上。所以eBay所做的就是把这么多的数据库按照功能的不同切分成不同的种类:User Info, Item Info,Account, Billing, Product Information…每一类都有多个数据库。

image

紧接的一个问题就是怎么组织数据,这么多的数据库,给定一些数据,怎么知道这些数据应该存放在哪些数据库中?如果大家不遵从统一的标准,很容易造成混乱的。所以在eBay有一些统一的数据库建模标准:

2. Group data using standard data modeling techniques

这些规定主要是3个方面的:

  • Cardinality(1:1,1:N,M:N):是一对一,还是1对多,还是多对对?
  • Data relationships 数据之间的关系
  • Usage characteristics 使用这些数据的特点

在有这么多数据库的系统中,Logical Hosts的概念非常重要,其思路很简单,但是非常有用。

3. Logical Hosts

放了方便应用程序的开发,应用程序层和数据库进行交互的时候,并不知道正在和自己交互的是哪些物理数据库,应用程序只知道逻辑数据库。而逻辑数据库和物理机器的映射是由专门的模块负责的。这样的好处就是:当我们移动物理数据库的时候,应用程序层不需要code change。比如Capacity不够的时候,我们把数据库搬到容量更大的机器或者利用Partition原理加入更多的物理数据库。又或者我们可以把多个逻辑数据库部署在同一个物理机器上。

  • Abstract application’s logical representation from host’s physical location
  • Support collocating and separating hosts without code change

这样一来,对于Operation Team来说,也更加方便灵活。

 

 

[Databases]:Horizontal Split

当我们提到User Host,我们不是指一台服务器,我们是指多台服务器。假设我们把所有的User信息分成20份(20个partition),第一个1/20的User放在UserHost0,第二个1/20的User信息放在UserHost2…

  • Split databases horizontally along primary access path。

确定了Partition的数目,那怎么来决定哪些User是第一个1/20,哪些是第二个1/20的呢?主要是根据如何访问这些数据的,我们的希望是能把数据平均的分配到这些Partition上去,这里说的平均不单单是指数量上的平均,更重要的是访问时候流量的平均。所以设计的时候主要考虑访问方式!

  • Different split strategies for different user cases。

现在主要有两类策略:

  1. Modulo on key(item id, user id,etc.) 根据模值进行Partition。
  2. Lookup or range-based。

这里我想补充一点,在这个PPT里面所提到的Partition是个通用的概念,和Split是等同的。并不是专指Oracle 里面的Partition Table。我们完全可以有多个Split的数据库,每个数据库里面的数据表再进行Partition。

  • Aggregation/routing in Data Access Layer(DAL)

image

同样,我们不希望这样的Split会对应用程序层造成影响。应用程序不需要关心要到哪个物理机器上去哪数据,在Partition的情况下,应用程序也不需要关心我的数据到底在哪个Partition数据库上。这些繁文缛节都有DAL来处理。DAL还负责将数据库操作(Create/Read/Update/Delete) "Routes"到相应的Split(s)上去。

如果随着时间的推移,eBay发现原先的Partition并没有很好的Balance数据,需要做Rebalance,比如说本来Item是按照模10进行Split的,现在随的登录物品的增多,需要增加数据库,变成模20进行Split了,这样的改变不应该导致应用层受影响。

关于在Split情况下,应用层和数据库部署细节的隔离,Randy的原文是:

  1. Abstracts developers from split logic,logical-physical mapping
  2. Routes CRUD operation(s) to appropriate split(s)
  3. Supports rebalancing through config change

到这里,我以为关于数据库的Partition的介绍就完了呢。然后Randy开始介绍一段非常有eBay特色的项目,他先问了个问题,这么多分布的数据库,一个业务逻辑需要跟很多数据库打交道,牵涉到很多表,而这些数据库,数据表又分布在不同的地方,怎么保证操作的正确性,原子性。但是我没有想到Transaction在这样的环境下所面临的挑战。

今天写这篇学习笔记的时候,让我想起来几天天看数据库系统概念(Database System Concepts)里第6章开始的几句话[The Task of creating a database application involves several tasks]:

  1. Design of the database schema
  2. Design of the programs that access and update the data!
  3. Design of a security schema to control access to data

千万不要设计出来的东西,样子很好看,理论上很漂亮,但是在实际中不能用,或者用起来常出问题,或者维护成本很高。

 

 

Partition Everything[Databases]->No Database Transactions

我在标题上使用’->’表示No Database Transactions是一个推论(Corollary)。是因为eBay采用了前面介绍的Partition Everything的策略所造成的。这里我先列出eBay的事务策略,然后再逐一解释。

  • eBay’s transaction policy
    1. Absolutely no client side transactions,two-phase commit etc.
    2. Auto-commit for vast majority of DB writes.
    3. Anonymous PL/SQL blocks for multi-statement transactions with single DB.

eBay不使用(explicit) transactions,准确的说是不是用distributed transactions。也就是说我们从不start an transaction, 然后做很多操作(operations),最后commit那个transaction。在eBay,大多数的情况是这样的,假设我们要做3个操作,我们做第一个操作,然后commit,我们做第二个操作,然后commit,我们做最后一个操作,然后commit,很多时候我们看到的SQL都不复杂,就是只有一个statement,所以多数情况下的DB操作就都是auto-commit的(implicit transaction)。如果碰到我们一定要把很多操作捆绑在一起放在一个事务中处理,就需要走另外的流程了。也就是上面提到的第3点–anonymous PL/SQL blocks,本质上这样的block就是在DAL层的store procedure,都是小心翼翼的手工写的,这样是为了能够让多条statements,在一个调用中由一个事务完成。

<注:关于anonymous PL/SQL block我还是不太理解,我到eBay后也从来没有碰到过,下个礼拜去问问COC的DBA,看看有什么收获。>

Randy在这个时候跟我们开玩笑说,上面提到的方法不是我们学校里面学到的方法,也不是我们在进行数据库编程的时候常用的方法,但是上面的方法是目前eBay能够进行Scale的唯一可行的方法。原因是:(Here’s WHY)

eBay的大多数业务操作,比如用户竞价一个物品(make a bid),或者列一个新物品(list a new item),都牵涉到很多数据库实体(数据库实体指实体表或者关系表)。可能牵涉到的实体有:User, 一个item,或者是多个item,或者是多个User。而我们所要进行交互的不是一个数据库,而是多个,甚至上百个,甚至上千个。上面所提到的操作(make a bid, list new item…)常常有好几个步骤才能完成,问题是:非常非常有可能(typically),其实事实上也是,属于同一个业务操作的不同的步骤会在不同的database上执行。我是一个seller,我的信息在 seller数据库上,我卖一个物品给buyer,buyer的信息在另外一个数据库上,有人bid我的商品,item的current price要更新,这些信息在item的数据库上…如果我们要做一个distributed transaction的话,我们做的就是一个two-phase commit。这意味着一个业务操作中牵涉到的多个数据库操作要么同时成功,要么都不成功。实现这种方法的常用手段就是locking!这会降低系统并发,首先受到影响的是performance,速度会很慢。而且对availibility的影响也很大,举个例子,假设list a new item要牵涉28个数据库操作,从理论上来说,这28个操作有可能会在28个不同的数据库上执行,想象一下把这28个操作放在一个distributed transaction中执行,意味着锁住了28个数据库资源,在那么大的用户并发情况下,eBay站点会怎样,用Randy的原话是: It will go into a hell!

但是我们仍然需要保证consistency。eBay是怎么做到这一点的呢?

  • Consistency without transactions
  1.  
    1. Careful ordering of DB operations.
    2. Eventual consistency through asynchronous event or reconciliation batch.

比如list a new item。eBay不要求所有的28个数据库操作都在同一时间完成,有些步骤可以晚些执行。在没有distributed transaction的情况下保证数据一致性的第一招就是:

小心翼翼的安排多个数据库操作的执行顺序!

举个例子,如果我们有一个master record,关联着10个children records。通常情况下,我们会先插入那个master record然后再插入10个children records。因为我们学习数据库设计的时候就是这样的,children records表中还有一个到master record的外键呢!而在eBay,操作顺序是反的,先插入children records,如果都成功了,再插入master record。原因是,如果我们先插入 master record,成功了,但是在插入children record的时候出错,因为没有事务机制,数据就不完整了。但是如果先插入children records成功了,在插入master record的时候出错,由于master record没有,逻辑还是对的。唯一的问题是我们在children records表中有了垃圾数据,那怎么样呢?没有关系的!Randy的原话是:"well, that’s O.K.-:)"

第二招就是eBay使用异步事件来纠正inconsistency!比如一个业务操作有10个步骤,在进行到第5个步骤的时候出错了,就发送一个异步事件让该事件负责对前面的4个步骤进行“善后”。

这里解释一下什么叫做reconciliation。这是一个在银行系统中常用的概念:http://en.wikipedia.org/wiki/Bank_reconciliation
"Bank reconciliation allows companies or individuals to compare their account records to the bank’s records of their account balance in order to uncover any possible discrepancies."

eBay也使用了这一技术,特别是在billing中。我们注意到异步事件和reconciliation batch都无法保证immediate consistency,但是我们需要immediate consistency吗?或者说eBay有能力鱼与熊掌兼得吗?

  • Consistency is not always required or possible(!)
  1.  
    1. To guarantee availability and partition-tolerance, we are forced to trade off consistency(Brewer’s CAP Theorem).
    2. Leads unavoidably to systems with BASE semantics rather than ACID guarantees.
    3. Consistency is a spectrum, not binary.

在计算机科学中有一个CAP理论,意思是,如果你有一个系统,你Partition了这个系统,而且你要求这个系统有High Availibility,那你就不能同时实现immediate consistency。Immediate Consistency、High Availibility和Partition Infrastrunture,只能同时拥有其二。

 

 

Partition Everything[Databases]->Minimize Database Resources

eBay数据库Partition的第二个推论就是:因为eBay的数据库系统使用率非常高,很多业务都严重依赖数据库系统,所以为了让数据库更好的为更多的应用服务,需要尽量减少单个应用对数据库服务器的资源消耗。

  • No business logic in database

在数据库上没有业务逻辑,这就意味着:

  1. No stored procedures
  2. Only very simple triggers(default value population)
  • Move CPU-intensive work to applications

将所有的大量耗费CPU资源的工作全部移到应用程序中来做,这一点上次我参加COC DBA给我们做的Basic SQL Tuning培训的时候已经听过一次,这次Randy再说一遍就理解地更深刻了。比如Join,两张表的Join本来就耗费资源,况且在Partition Everything的情况下,非常有可能这两张表是在不同的数据库服务器上的。下面3点是典型的 CPU intensive的操作:

  1. Referential Integrity
  2. Joins
  3. Sorting
  • Extensive use of prepared statements and bind variables

这一点我想不单单是eBay,其他的网站,应用也都应该这样做的。

好,到这里,Partition Everything中关于数据库的部分就介绍完了。接下来将会介绍应用层的Partition。