Scaling with IMDG.(利用内存数据网格进行伸缩)

说到伸缩性,我们一般都会想到存储的伸缩以及本身应用程序的伸缩,下面这篇文章讲解了对传统的关系数据的伸缩以及如何通过内存数据网格来进行应用程序的伸缩。

首先对于传统的RDBMS的伸缩,大家比较熟悉主要有以下两种方式:

Database replication:这也是经典的Master/salve模式的实现,这种方式最大的优点就是通过增加savle来进行read操作的负责均衡,是一种对read的scale out方式,但是同时这种方式也存在以下的缺点:
1 只是适合于read 频繁的情况,Database replication方式通过多个replica 来对read进行伸缩,但是对于write操作则不能进行scale out.

2 性能问题,因为数据库操作是一种磁盘io操作

3 一致性(consistence),关于这个问题,如果深入讨论可以独立写一篇文章来进行讨论,这里简短的说一下,Master/savle中,如果采用异步复制,那么不同的节点的状态可能是不一致的,相反的如果采用同步方式,那么又会造成很大的延迟。

4 容量问题,复制(replication)技术要求每个节点保存完整的数据,这就带来了两个问题,第一个问题就是对于每个节点来说,数据还是会变得越来越多,这样查询的速度也会相应的变慢,第二个问题就是我们需要提供N+1倍的存储空间。

5 复杂性以及非标准化问题,大多数的数据库复制技术都是相对复杂的,同时不同的厂商所采用的方式也是不一样的,这样就会造成应用和存储的依赖性。

Datebase partitioning:这种方式也就是大家熟悉的数据库sharding技术,这种方式使得数据库中数据分布在多个节点上面,这样每个节点都存储一部分数据,这样的好处就是可以对read和writer操作都具有一定的scale out,但是同样这种方式也存在以下的缺点:
1 要求应用程序的数据必须是能很容易切分的。

2 性能问题,因为数据库操作是磁盘IO。

3 要求改变数据模型,很多的数据sharding技术都要求应用程序知道数据在哪一个partition上面。

4 需要改变应用程序代码

5 静态性,在许多的数据库实现中,当增加Partition的时候,都要求重新的划分partition.相反的目前流行的key-value存储系统通过consistent hashing解决了这个问题。

6 复杂性以及非标准的

前面是针对传统的数据库对scalability的解决方案,下面作者指出了如何通过内存数据网格(In-memory date grids)来进行应用程序的scale out.

在说IMDG之前,作者也指出了目前很多互联网公司采用的方式:通过内存缓存来scale out应用程序,目前比较经典的做法就是在DB前端引入分布式的缓存系统(memcached,terracotta等),这样可以对大部分的读取操作进行非常有效的scale out,但是此种方案还是没有解决对write操作的scale out。

下面就说说IMDG对scale out的解决方案。
作者指出了Paas(Persistence as a service)的说法,说白了就是将对象和数据的持久化仅仅当做是一种服务而已,以下作者以问答的方式阐述了几个常见的问题。
1 Paas如何工作

利用Paas,IMDG将会屏蔽到数据库,内存IMDG和底层数据库的同步操作由IMDG来完成,这种内存和数据库的同步可以通过异步的方式来进行。

2 Paas和RDBMS相比是如何提供性能的
2.1 Paas依赖内存来存储系统的状态,而内存操作和磁盘IO操作来比是非常快速的,同时也支持更大的并发访问。

2.2 因为是内存存储,所以数据访问通过内存引用或者指针,而不需要序列化的开销。

2.3 数据操作直接针对内存对象

2.4 减低了竞争条件,这种方式是将数据分配到多个内存节点上。

2.5 并行的聚合查询,这种方式非常类似Map-reduce并行计算模型,它是一种将计算移动到存储数据的节点进行并行计算的方式,这样将会更好的利用CPU和内存资源

2.6 避免了ORM,读取操作直接从内存进行,避免了ORM的开销,ORM只是在初始化的时候进行。

3 如果要同步数据库,那么此种解决方案不会受到数据性能的影响吗?
不会,原因如下:
3.1 数据以批量的方式异步的同步到数据库。

3.2 更新操作是可以在多个Partition节点并行的进行

3.3 更新操作发生在和需要更新的数据在同一台物理机器上面,这样避免了网络开销.

3.4 我们不是为了高可用性的目的来使用RDBMS的,RDBMS是一个强一致性,低可用性的解决方案(CAP理论), 采用IMDG所有的查询操作都是直接的内存操作,而只有update和insert操作才会触发数据库,并且这个时候会以partition的方式,也就是说write操作也是被scale out的操作。

3.5 应用程序和数据库现在是松耦合的,这样更加方便进行优化

4 异步的同步IMDG和数据库是不是意味着当失败发生的时候,数据可能会丢失?

IMDG会进行backup,当一个节点发生失败的时候,备份节点会接着进行,所以不会失败。

5 如果其中一个内存节点失败会发生什么问题?
这个问题非常类似于hadoop的Namenode和datenode节点模型,熟悉hadoop的朋友应该能容易理解。

6 如果数据失败会发生什么问题?

IMDG会保留一个记录所有更新和插入的日志,当数据库失败的时候,更新和插入操作还会继续,不会影响到系统终端用户,当底层数据库再次可用的时候,IMDG会根据日志来同步数据。

7 IMDG怎么处理事务完整性?

大家都知道2PC事务是一种反伸缩性的实践,它使得所有的partition耦合在同一事务当中,目前比较好的做法就是将事务分为几个小的事务,每个小的事务都在单独的partition上面完成,这样即使存在部分partition失败,但是IMDG还是会保证整个系统处于一致性的状态。

下面我发发牢骚。
目前随着互联网的的快速发展,对于一些热门的应用会造成非常大的读写压力,尤其是目前社会化网络使得传统的RDBMS更加受到打击)Social Media kills the RDBMS

说到伸缩性,我们一般都会想到应用程序本身的伸缩和存储的伸缩,应用的伸缩要求我们对应用程序进行合理的切分,按照功能,按照层的方式进行,而存储的伸缩,传统方式采用复制,sharding等方式,但是这种方式是有很多限制的,限制上面也说了。因此我们如何寻找一种能对read和write都具有scale out的解决方案就成了目前一个难题。幸好,目前NOSQL运动给我们带来了福音,通过分布式的key-value存储系统可以更好的对read和write操作进行scale out.

比如像Twitter这样的应用,它是一个读和写都很频繁的应用,采用传统的解决方案肯定是不行,因此需要一种新的解决方案,这就要求我们吸取NOSQL运动的思想,Twitter每天的有100亿条数据写操作,因此这么频繁的write就需要通过consistent hashing根据用户的ID或者名称来进行均匀的切分,比如hash(userID)%node_number,这样又会造成一个问题,就是读取操作怎么办?因为通过切分,不同的用户被分配到了不同的虚拟节点上面,那么一个Twitter用户想要读取最新Tweet的时候就需要从多个节点进行读取,这个时候就需要利用map-reduce的思想,通过移动运算到存储数据的地方,最后在聚合所有的查询操作(在客户端进行reduce操作.

因此我觉得OO+分布式的存储(key-value)+分布式并行计算(Map-reduce)将会是以后的一个发展方向,当然如果采用这种方式前提是应用数据量大,同时要求应用要能很好的进行切分。

讲的真好,让我想起了voldemort的架构图(可惜找不到那片文章的链接了-_-||),后台一批的db集群,通过map-reduce抽取数据,推送到缓存给应用读取,而db群完全可以换成key-value存储系统。我觉得现在nosql的理论和框架已经非常成熟了,只是在国内还缺少一个成功的实践而已。如果banq大哥能将jdon论坛移植到key-value系统,那也算是给这个东西做个了结,让大伙觉得这东西还真是那么一回事,心里有谱~~

我很喜欢“Social Media kills the RDBMS社交媒体杀死了关系数据库”这句。这篇文章也值得一看。

社会媒体(或称社交媒体)是一场革命,facebook twitter Hulu都是先驱,现在国内中央电视台等传统媒体纷纷开通网络电视,表示他们对社会媒体的重视。

程序员做软件时,必须对自己软件行业进行分类,是企业软件?还是社交媒体软件?

当然,这个界限越来越模糊,特别是我们知道他们区别的背后本质:CAP定律。