上一篇中,谈了一下我所理解的架构。其中提到了一条基本原则:Don't communicate by share memory, share memory by communicate instead。并说了一下关于对归属的理解。这一篇中谈谈另一个基本原则:移动计算而不是移动数据。
最早接触到这个概念应该是在近来炒得很火的大数据中,mapreduce就是典型代表。数据是分布存储在各个机器上的,为了使用这些数据进行计算,并不是移动数据去适配计算,而是移动计算,map过程实质就是移动计算。因为这种条件下移动计算的成本是比较低的。
mapreduce是受lisp语言启发的,说到lisp,还有另一种形式的移动计算的魔力,这个应该归功于它的代码即数据。就是RPC只需要把代码发过去在另一端运行就可以实现了,想远程那边跑什么计算,就发送什么样的代码过去。其实这种能力也不仅仅限于lisp,应该说带虚拟机的脚本语言都可以实现这种性质。
将这一点使用到极致,令我感触最深的,应该是剑三中的插件系统(魔兽世界没玩过)。剑三中的做法,应该跟云风博客描述得着不多:每个玩家在服务器端都对应了一个lua虚拟机的agent。插件是用lua语言写的,有了agent,那么插件系统就顺理成章了,客户端直接把lua代码发送给agent,agent执行这些代码,把结果告诉客户端--瞧,这就属于典型的移动计算而不是移动数据。
按照移动数据的做法,就是一个一个的封包的交互,客户端想要某东西的计算结果,而计算依赖于数据(状态是在服务端),数据不在本地,所以发消息包的方式就像是把输入数据发过去,计算原本就在另一边(不景移动过去的),然后再把输出数据发回来。用这种方式显然无法实现也剑三那样的插件系统的。
而使用移动计算的做法,我需要对数据进行计算的结果,那么我把要执行的代码发到另一端就行了,计算自然是跟着代码过去的。
PS,在我接下来想做的东西中,用goroutine实现的agent,没有lua虚拟机,不能接受计算。但是我又想要类似这种插件系统的能力,因为这样客户端写起来会方便很多。我初步打算这一块用RPC实现。
Read full article from 关于架构(续)
No comments:
Post a Comment