微服务下持久化观念转变

2018-04-03 13:22:03 浏览数 (1)

过去当我们开发一个企业应用的时候,我们经常首先会考虑的是“我们怎么和数据库交互”?最近的一两年来,人们慢慢的开始转变了,可能要问“我应该用哪种类型的数据库?是用关系数据库还是NOSQL数据库”。然而,我们是不是应该再更进一步,是不是要开始问“我们要不要使用数据库”?

企业应用程序的一个关键特征是需要存储长期数据,这自然导致人们首先想到数据库。毕竟负责把数据持久化是数据库主要做的事情。通过使用内存镜像(memory image)是处理持久化完全不同的路,这个条路并不直接涉及到数据库。

内存镜像(memory image)的关键元素就是使用事件源(event sourcing),这实质上意味着对于应用程序的状态的每次改变都被当作一次事件追加到一个持久存储库(persistent store)。而且,这意味着您可以通过replay这些事件来重建完整的应用程序状态。在这种做法下,事件就变成了最主要的持久化机制。

使用事件源的一个熟悉的例子就是版本控制系统。每个更改都被捕获作为一次commit,您可以通过replay这些commit 来rebuild最近状态的代码库到一个空的目录。当然,实际情况下重播所有事件太慢了,所以系统会定期持久化应用程序状态的快照。有了快照以后,重建数据就只涉及到去加载最近的那个快照并重播自该快照以来的那些事件。

事件源(Event sourcing)涉及到很多东西,包括重建过去状态的能力等等。但是,内存镜像(memory image)最主要的一点就是,我们不用再去担心应用程序的状态是不是在最新的持久化数据库中。相反,我们可以将应用程序的状态保留在主内存中。如果进程崩溃了,我们依然可以从事件(和快照)中来重建它。

使用内存镜像可以让你获得更好的性能,因为我们是在内存中完成所有操作,无需IO或远程调用数据库系统。而且更重要的是,这意味着你可以摆脱那些和数据库映射的相关代码,也不用担心内存状态和数据库状态之间的同步。

但是说了上面那么多,并不意味着我们就甩手掌柜什么都不用担心了。既然现在转移到事件了,那就必须要保证事件要被可靠的存储,并且要保证可靠的处理消费这些事件。这也是为什么现在公司内消息中间件团队要比过去担负更重要的责任,事情也要比过去更多。而且你还需要去写一些代码来保存和加载快照并且能够以足够快的速度恢复系统,从而保证你的服务质量。过去数据库支持事务性的并发能力,现在你也要做一些事情支持并发。

另一个相当明显的限制就是,你必须要有更多的内存来保存你的数据。

很多情况下都可以使用内存镜像,下面就来举几个例子。

最近的一个例子就是LMAX。 LMAX是一个高性能交易系统,它在单个JVM线程上处理600万TPS。在这里,内存镜像的性能优势显然是一个重要因素,但他们发现编程模型的简化同样重要。他们不必担心并发,所有的都是单线程来搞定。为了保持高可用性,它们运行多个内存镜像副本,这样的话,如果一个死掉,它们可以切换到另一个实例,与此同时还能保持很高的事务处理速率。

最古老的例子就是Smalltalk开发环境。大多数开发工具依赖文件系统中的文本文件,该文件系统根据需要进行编译或解释。然而Smalltalk将所有的源代码和编译方法都保存在镜像中。你执行的每个命令都存储在更改日志中。大部分时间你保存你的image(快照),但如有必要,你都可以从稳定的base中回放更改日志,比如你手滑做了一些愚蠢的事情的时候。

像这样的做法已经被使用了很多次,也被无数次的推荐,但从来没引起主流的重视,通过数据库来持久化数据依然是更常见的做法。

我听说过内存镜像的一个问题是迁移。任何时候建立一个软件系统,了解它将如何处理更改都很重要。使用内存镜像这种机制,本质上做的事情就是你要确保时刻都能从事件日志中重建内存镜像。

这里的一个陷阱就是是事件日志所使用的序列化结构,你哪天想要修改事件的结构,那么可能是行不通的或者说很困难。如果您创建了一个特定的事件类并将其序列化,则可能会在以后更改事件类的结构时难以处理旧事件。通常最好还是使用通用的数据结构来进行序列化,比如map、list。

同样重要的是在事件和模型结构本身之间要保持良好的解耦。可以尝试去搞一个事件数据和模型的自动映射系统,但是这样就把事件和模型耦合到一起了,让我们的迁移模型变得更加困难,而且还依然要去处理那些老事件。

在某些时候,我们需要将事件日志本身从旧格式迁移到新的格式。迁移事件日志是个比较麻烦的事情,但是从一开始就慢慢演进可能是一个不错的选择。不要总是想着拉到重来,演进总是没错的。

很长一段时间,反对使用内存镜像的一个大的论据是就是内存大小,但现在大多数商用服务器的内存都可以很大。所以,现在大多数情况下我们都可以安全地保存在内存中。也许几年前你还会有所顾虑。但现在随着NOSQL运动,人们也许正在重新考虑他们的持久性选择,也许在不久的将来,内存镜像(memory image)会成为一个重要选择甚至可能变为主流。

from Martin Fowler

0 人点赞