一个关于模块间RPC的问题
发布于 1 年前 作者 hellolw 754 次浏览 来自 问答

最近做的一个demo,基本流程跑完了。开始考虑重构,现在有这样一个问题,我需要操作数据库,而且可能存在多线程并发访问的问题。 最初的想法是,直接做一个DB管理模块,模块间通信使用rabbitmq,其他模块对DB的操作都扔到队列中,DB管理模块从里面一个一个的取,依次完成DB的读写操作,这样可以避开MYSQL的多线程问题,简化对DB操作。 但是今天又看了一下 mqant/wiki/ 里面 mqant中的RPC 这一节,有如下描述 1,“自动选择通信方式,对开发者完全透明,当被调用模块在同一个进程中时使用golan chan” 这样的话,如果我把DB管理模块和其他业务模块放在一个进程中,那么就不能使用rabbitmq了,对于我的而言,这样又需要考虑MYSQL多线程的并发处理。

2, RegisterGO与Register的区别是前者为每一条消息创建一个单独的协程来处理,后者注册的函数共用一个协程来处理所有消息,具体使用哪一种方式可以根据实际情况来定,但Register方式的函数请一定注意不要执行耗时功能,以免引起消息阻塞 这句的意思,是不是意味着如果用Register方式而不是RegisterGo方式,那么就能保证单线程执行了?但是这样的话, golan chan的缓存有多大,是否存在可能缓存满的情况。

希望有这方面经验的朋友能给点建议

5 回复

数据库库操作据我了解mysql应该可以通过事务来实现一些逻辑锁的处理的,我比较建议你将功能按模块的形式来划分,而不是笼统的按数据库去划分模块,对一个功能的操作都放一个模块中,尤其是写操作放一个模块,可以更好的管理。至于读操作各个进程都应该可以去读取,不太需要太关心并发问题。 RegisterGo与Register的选择还是要看实际情况,Register我现在的用法是用在接收客户端发送过来的消息这块,Register接收到的消息对直接填入游戏房间自己的消息队列中,房间内部有一个定时器按每帧(25ms)的节奏来统一处理这些消息(同一个协程内处理的)。因此使用Register的意思是需要你自己去想办法处理并发和多线程之间的关系。在同一个协程中处理请求当然可以避免线程锁,但同样限制了请求的并发处理量,因此一般的web请求我都是通过RegisterGo来处理的,只有每一个房间的内部消息因为每秒请求量可控我才使用的Register来处理

@liangdas 看了一下go-database-sql的文档,貌似驱动中直接封装了一个connection pool,只要并发数量不超过max_connections,访问数据库应该都没什么问题。 那就先不考虑这个了,接着往下做

嗯只需要数据库操作的时候事务问题考虑好就行,不要前一个请求处理对同一个数据处理到一半,另外一个请求又来处理,主要就是资源锁定好,你说的数据库请求的多线程问题应该数据库的操作库已经给你处理好了,不需要太关心

我的思路和@hellolw一样,用独立的数据库服务模块处理游戏存储业务。不然的话,用到数据库的模块都要去管理建立数据库连接,比较麻烦。 但是数据库查询的时候也通过一个单独的模块来中转的话可能对这个模块的压力会很大,如果一个功能一个模块来设计每一个模块负载会小一些 写入者唯一是我始终坚持的一个原则

@liangdas 25ms的定时器怎么设置,settimer是int32的秒单位? 这是golang的知识,自行百度,我是用了一个linux时间轮算法,只用了一个定时器来处理所有房间的定时调用

回到顶部