bug about redis/socket module #51

Closed
wesom opened this Issue Oct 26, 2013 · 8 comments

Projects

None yet

2 participants

@wesom
wesom commented Oct 26, 2013

the debug info:
[64000010] lua call [0 to :64000010 : 0 msgsz = 24] error : ./lualib/skynet.lua:81: ./lualib/socket.lua:241: assertion failed!
stack traceback:
[C]: in function 'assert'
./lualib/socket.lua:241: in function 'lock'
./lualib/redis.lua:112: in function 'get'
调用场景:A,B两个service,B有db连接,A 先send消息给 B写数据, A 再call B读取数据,会出现上述bug信息,如果把第一步send改为call方式则正常。如果多次send再call,会读到错误数据。

@cloudwu
Owner
cloudwu commented Oct 28, 2013

对 redis 连接的处理, 利用了 socket 库中的锁机制. 对同一条连接, 可以通过加锁来保证不同的 coroutine 依次去完成一个完整的业务(写一次,读一次)

  1. 我按描述写了测试程序, 无法重现错误.
  2. 从 assert 信息看, 是由于同一个 coroutine 连续发起了两次 lock 请求. 但是, 按描述, B 每次接收到 A 的请求, 无论是 send 还是 call 都会生成一个新的 coroutine . 按设计, 第 2 次 call 的时候会因为第一次 send 引发的写操作正在执行而等待解锁, call 和 send 两个请求不应该在同一个 coroutine 内, 不会导致 assert 发生.

请帮忙检查一下具体问题.

多次 send 再 call , 会因为多次 send 的写操作解锁次序随机而后发的操作先执行. 这是不合理的, 我正在修复这个 bug , 让加锁和解锁有序.

@cloudwu
Owner
cloudwu commented Oct 28, 2013

我改写了 lock 的实现,增加了队列. 但我无法重现案例 1.
请测试一下是否还会出现 assert

@wesom
wesom commented Oct 29, 2013

案例1的描述不太准确,我自己特别写了一个测试用例,简单设置一个key, agent -> A , dbproxy-> B
step 1: A call B
step 2: A send B
step 3: A call B
我用python简单模拟客户端发送3个消息包,每次均可重现案例1(出现之前的bug info),更新queue lock补丁后虽然不再直接报错,但第3步的call无返回,且再次登录不响应任何消息
先report下测试情况,目前还在阅读源码,暂不清楚真正原因

@wesom
wesom commented Oct 29, 2013

默认call --> read,send --> write

@cloudwu
Owner
cloudwu commented Oct 29, 2013

不响应多半是因为 unlock 没执行到,后续操作获得不了锁的缘故。请结合测试程序查一下。

在 2013年10月29日星期二,wesom 写道:

默认call --> read,send --> write


Reply to this email directly or view it on GitHubhttps://github.com/cloudwu/skynet/issues/51#issuecomment-27292453
.

http://blog.codingnow.com

@cloudwu
Owner
cloudwu commented Oct 29, 2013

这个问题可能和复用 coroutine 处理消息有关. 我明天再仔细查一下.

@wesom
wesom commented Oct 30, 2013

测试通过,不过修复的有点小问题,self.__mode在lock时,应该是false or write or read
assert(not self.__mode and (mode == "read" or mode == "write")) -->
assert(mode == "read" or mode == "write") 否则测试中会报错

@cloudwu cloudwu added a commit that referenced this issue Oct 30, 2013
@cloudwu fix Issue #51 feb2efd
@cloudwu
Owner
cloudwu commented Oct 30, 2013

不太建议用 batch 模式, 而且这个模式在很多别的 redis driver 实现中也是没有的. 有同学建议去去掉.
如果制作 db proxy , 建议实现成一个连接池, 每个 db 请求收到后找一个空闲的连接,在上面进行操作.

@cloudwu cloudwu closed this Oct 30, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment