当逻辑编程遭遇CQRS时

我们将看到逻辑编程能做的最令人兴奋的事情之一是实现CQRS模式。Eve语言将CQRS这个理想的设计模式变成了现实。

你知道Eve是一种逻辑编程语言吗?Eve是基于Dedalus ,这是一个Datalog的扩展数据记录 ,Datalog是基于Prolog的逻辑编程语言的。

逻辑编程的工作方式是:你写下一堆事实,然后你能基于这些事实立即得到一个世界,其中所有他们的逻辑含义是真实的。

Datalog自20世纪70年代以来一直存在。但是,如果逻辑编程如此伟大,为什么它没有走向主流呢? 也许是因为它比过程化或函数式编程不那么直观?

不,我认为逻辑编程魅力到现在还没有完全释放出来。Dedalus的研究报告在2009年就出来了,它看起来对我来说,一个重大的理论进步。

Dedalus不同于传统的逻辑编程,显式地通过不可靠的异步通信信道随时间根据发生的事实不断更新模型,。 Joseph M. Hellerstein,Dedalus的合着者之一,是这样描绘它 :

对于那些喜欢数据库理论者,Datalog可能会使一些人惊讶,因为没有办法更新和删除模型。通过将时间合并到Dedalus逻辑中,将更新和删除操作作为对逻辑时间戳(版本化)数据的演绎的捕获。

当然,Eve现在才出来。 所以我们刚刚开始看到逻辑编程的潜力。

我想我们将看到逻辑编程能做的最令人兴奋的事情之一是实现CQRS模式。

命令查询责任分离(CQRS)是一种长时间时髦的词语,它只是意味着读取模式从你写模型中分离。
例如,在CQRS和事件溯源中 ,您的应用程序的写模型就像是事件对象的单只追加序列:

{event: “deposited", accountId: 123, amount: 100}
{event: “deposited", accountId: 456, amount: 100}
{event: “withdrew", accountId: 123, amount: 30}

而你的应用程序的读模型看起来更像:
{accountId: 123, balance: 70}
{accountId: 456, balance: 100}

当应用程序接收到事件(例如,存款)时,它会向写模型发出更新。当您的应用程序需要数据,例如获取帐户的当前余额时,它会查询读取模型。同时,你会告诉数据库层如何始终保持读模型与写模型同步。

事件溯源天然具有高可扩展性,高可靠性和高可靠性等应用流行模式。 这句话是Greg Young讲的。

即使你不关心事件溯源,你可能关心数据的非规范化 。好的,只要你认为你只是“反规范化数据”,你实际上是在“预计算一个CQRS的读取模型”。

CQRS好像是一个无关紧要的简单的嗡嗡声, 但你可以看到它其实是一个重要的概念,对于命名和关注来说。


问题:CQRS现在不可能?
CQRS的问题是,从来没有一个好的方法来“告诉你的数据库层如何始终保持读模型与写模型同步”。 理论上,CQRS是伟大的。 但在实践中,它不够灵活和强劲。

那些声称能帮助实施CQRS的系统通常是流处理系统,例如:
1.事件存储
2.Apache Samza和卡夫卡为基础的解决方案


你也可以使用一个SQL数据库实现CQRS:只要把你写模型放入一个或多个表,然后使用触发器来应对变化并发出相应的INSERT / UPDATE / DELETE操作来同步你读模型数据库。

不幸的是,无论你选择上述哪一个,你都必须滚动自己的混乱过程逻辑来对输入的写操作做出反应。 也就是说,你必须告诉数据库如何保持两个模型同步。你不能够只是声明一下这两种模式之间的关系应该这样就行了。

此外,一致性保证是iffy。当写入模型更改时,您不能保证整个读取模型相应地从一个一致的快照到下一个快照。

物化视图模式
好吧,嗯.....使用物化视图模式实行CQRS?理论上,物化视图模式是伟大的。 但是在实践中 - 尽管有自己的MSDN页面 - 它缺少一个令人满意的实现! 物化视图仅适用于基本数据转换。 它们不够聪明,不能在写入模型操作的反应中增量更新自己。 加上它们的一致性保证是弱的。

我以前曾经指出物化视图的限制,当我渴望一个“反规范引擎”,我基本上是指任何优雅和健壮地实现物化视图模式的东西。

CQRS在我看来是一个关键模式,我们应该使用我们的数据层 -但目前很少看到一个具有优雅的CQRS架构的生产系统,甚至在谈话中提到“CQRS”时也是这样。

逻辑编程符合CQRS
很快,我们不需要物化视图模式,SQL触发器或流处理 - 因为我们会有Eve。
最新版本的Eve,0.2,只是一个内存中的演示; 它还没有顶得上数据库但足够了。但我敢说它已经走上了成为最佳实施的CQRS。

在Eve,使用search和bind的块是像定义一个物化视图。 这里是一个记录物化视图/ CQRS事情:


search
[a]
[b]

bind
[c:a+b]


search
[a]
[b]
[c]

bind @view
[value value: "a={{a}}, b={{b}}, c={{c}}"]

结果:
a=5,b=6,c=11


这里我将c总是绑定等于a + b 。 现在a是5 , b是6 ,c就是11 。 如果我增加b至7 ,然后我会自动显示的c值12 。

看,这是CQRS! 我的写入模式是a和b ,以及我的读-模型是c 。

这是一个简单的例子,但它说明了核心概念。


使用Eve的bind操作,你可以用你写模型同步到您的读模型,使得模式CQRS成为现实。


现在,我们已经看到,逻辑编程是一种很有前途的方法,使CQRS变成现实,我还要提到Datomic ,今天也许是在市场上最知名的逻辑编程数据库。

When logic programming meets CQRS