关于监听同步模块的封装
为啥需要封装一个监听同步模块?
使用skynet
开发功能,由于是actor模型,难免会遇到一个服务需要依赖另一个服务的数据的情况,解决这个问题常见的方案有:
封装一个c模块,用于共享数据
优点:- API使用简单,get set 即可。
- 节省内存。
缺点:
- 编码难度大,风险高,需要处理好多线程编码问题。
- 需要加读写锁,读取性能不一定高。
- lua调用c,没有直接访问lua快。
要用的时候去查询
优点:- 实现简单,简单call调用即可。
缺点:
- 对于过于频繁的请求,并不是一个很好的方案。
- 查询数据量大时,对性能有影响。(频繁的打包,解包,生成临时的
lua
表,增加lua gc 负担)
watch_syn监听同步机制
优点:- 实现难度适中。
- API调用简单。
- 数据本地持有,访问迅速。
- 更新通知,无需频繁请求。
缺点:
- 如果是频繁更新的数据,效果与第二方案没有多大差异。
使用案例
skynet的share_datad.lua
我学习到使用这种机制,是通过翻看share_datad的源码,share_data通过监听同步机制来实现对共享配置的热更。
skynet_flycontriner_mgr.lua
skynet_fly使用这种方式,通知热更后服务地址的变更。
skynet_flymonitor_exit.lua
skynet_fly使用这种方式,监听服务退出。
skynet_fly_demomonitor_exit.lua
skynet_fly_demo使用这种方式,通知密钥变更。
所以说,这种机制开发中,挺常用的,所有就打算写一个通用模块,以便以后使用直接引入即可,不需要去关心实现rpc的细节了。
实现思路
基本定义
监听同步机制中分为两个角色,发布者,订阅者,在代码中,我把他们分别称为server,client,server只有1个,client可以有多个,server可以发布多个key-value值,
client也可以监听多个key-value值,其中key是string,value,可以是string,number,bool,nil,table。client可以有多个,但是同一个服务里只有一个对应server的访问实例,因为server是以client服务地址为key记录来访,通常一个订阅者也不需要创建2个以上发布者访问实例。
机制链路
- server首先注册key-value,生成对应版本号为1。
- clientC2S 监听key,传递版本号首次为空。
- serverS2C 接收到key,如果不是首次访问或者版本号不一致返回最新结果,版本号一直暂时不回复(client会挂起等待)。
- serverS2C 当需要发布新值时,通知所有的监听的client。
通过以上步骤完成对数据的同步。
API
测试
关于监听同步模块的封装
https://huahua132.github.io/2024/01/28/skynet_fly_ss/watch_syn/