ShareData

当你把业务拆分到多个服务中去后,数据如何共享,可能是最易面临的问题。

最简单粗暴的方法是通过消息传递数据。如果 A 服务需要 B 服务中的数据,可以由 B 服务发送一个消息,将数据打包携带过去。如果是一份数据,很多地方都需要获得它,那么用一个服务装下这组数据,提供一组查询接口即可。DataCenter 模块对此做了简单的封装。

如果你仅仅需要一组只读的结构信息分享给很多服务(比如一些配置数据),你可以把数据写到一个 lua 文件中,让不同的服务加载它。Cluster 的配置文件就是这样做的。注意:默认 skynet 使用自带的修改版 lua ,会缓存 lua 源文件。当一个 lua 文件通过 loadfile 加载后,磁盘上的修改不会影响下一次加载。所以你需要直接用 io.open 打开文件,再用 load 加载内存中的 string 。

另一个更好的方法是使用 sharedata 模块。

sharedata 正是为了大量共享结构化数据却不常更新它们,这种需求而设计出来的。sharedata 只支持在同一节点内(同一进程下)共享数据,如果需要跨节点,需要自行同步处理。

local sharedata = require "sharedata"

可以引入这个模块。

  • sharedata.new(name, value) 在当前节点内创建一个共享数据对象。value 可以是一张 lua table ,但不可以有环。且 key 必须是字符串和正整数。
  • sharedata.update(name, value) 更新当前节点的共享数据对象。
  • sharedata.delete(name) 删除当前节点的共享数据对象。
  • sharedata.query(name) 获取当前节点的共享数据对象。

一旦 query 到一个共享数据对象,你可以像普通 lua 表那样读取其中的数据,但禁止改写。把其中的分支赋值给 local 变量是安全的,但如果你把最终的叶节点的值取出来后,就不可能被数据源的 update 操作更新了。所以,一般你需要持有至少一级表,每次用它来索引其下的数据。

一旦有人调用 sharedata.update ,所有持有这个对象的服务都会自动去数据源头更新数据。但由于这是一个并行的过程,更新并不保证立刻生效。但使用共享数据的读取方一定能在同一个时间片(单次 skynet 消息处理过程)访问到同一版本的共享数据。

sharedata 是基于共享内存工作的,且访问共享对象内的数据并不会阻塞当前的服务。所以可以保证不错的性能,并节省大量的内存。

sharedata 的缺点是更新一次的成本非常大,所以不适合做服务间的数据交换。你可以考虑它的替代品:stm 模块。


你可能感兴趣的:(ShareData)