扩展大型数据库
Scaling Large Database
一些超大型的信息聚簇难以进行联合。比如有一个非常大的用户表,我们不一定想把它分割成多个块,因为这样做之后,每次有人登录时,都不得不搜索所有的分区——我们必须找到用户记录,而且是在不知道分区号,只有用户名称的情况下。对于像这样的聚簇数据,如果要进行扩展,就需要某种具有很好的冗余性的多机器配置,有机器死机时,可以在线进行故障转移。这种要求无法通过复制(replication)设置得以方便地实现,因为其中的
主服务器(master)是单一故障点。相反,我们希望把数据同时写到集群中所有机器上,这样就能容忍在任意时刻损失任意一台服务器,而不会丢失任何数据。对于跨越一个集群的同步写,我们可以使用同步复制模式,或者自己来一次性地把数据写到所有机器上去。Oracle提供了一些同步复制模式,但在底层架构的一部分中使用Oracle,会引入又一种需要支持的复杂难懂的技术。MySQL的NDB提供了同步复制,但还没有做好大量使用的准备。
自己动手是目前仅剩的选择了,如何实现它呢?可以在每次需要写的时候,都向集群中所有的机器写。这意味着写速度取决于集群中最慢的节点,这还是可以接受的。如果写入的时候,一台机器死机了,那就真的碰到问题了——写操作由于这台机器出问题而停止了,也没有什么方法进行恢复。我们不能像在复制中所做的那样,停下另外一台机器,并且从它上面克隆。因为这两台机器会丢失克隆期间发生的所有写操作。真正需要的是类似于复制日志的东西——将所有的写操作记录成一份日志,这样就可以在当机的机器上重放这些操作。要建立这样的日志,那么就真地需要把所有的写操作放在一起;是时候添加另外一层了,如图9-17所示。

图9-17:添加写穿透缓存层
建立一个写穿透层,可以把保持多台机器处于最新状态的相关工作抽象出来,从系统代码中移出。写穿透层会接受SQL命令,并将它们传递给所有的节点,并且跟踪哪些节点是活跃的,哪些处于当机状态。当出现当机的节点时,就为它们记录下所需日志,一旦它们从当机的状态恢复,就进行日志重放。我们需要确保在写穿透层有多台机器记录这个日志,以避免这一层成为单一故障点。当节点起来后,就可以在所有机器上执行同步的写操作。集群中的一个节点总处于以下三种状态中的一种:同步、禁止或追赶(catching up)。我
们只想从处于同步状态的机器中获取最新的数据,但系统中唯一知道每个节点状态的组件就是写穿透层自己。如果把读处理也放在写穿透层,那么就能够只从处于同步状态的机器之中读取,确保获取最新数据。这种情况下,写穿透层可以成为驻留写穿透缓存的有效位置。可以做到在这一层缓存读数据,并且总是能够完美地设置不再有效的数据为失效,因为所有对数据的写操作都要经过这一层。这意味着写穿透缓存需要理解模式中的元素,以理解哪些数据它可以缓存,而不同于一个完全通用的体系结构,只是简单地复制写操作和平衡读操作。你是否需要这种程度的复杂性?这个问题的答案并不总是很明了,尤其是在有其他的缓存方法,并且它们工作得很好的时候。






