workerman 使用redis存储遇到的诡异问题

phpcreeper

如上图所示, 问题有三:

:11269 --> 即数字11269前为何会多出个冒号来?

不同的客户端为何查询到了相同的数据,比如图示 11271;

如何避免上述2提到的现象?

7629 3 0
3个回答

walkor 打赏

workerman分为主进程和子进程,如果主进程中创建了redis连接,在fork时子进程会继承redis连接,这样会导致redis返回数据时所有子进程都可读,导致数据错乱。所以不能在主进程创建mysql redis等连接资源。这部分在手册必读里有讲 http://doc.workerman.net/315119

如果连接资源先于Worker::runAll()运行前创建,那么就属于主进程。所以最好是在onWorkerStart回调创建连接资源。如果一定要在主进程使用一次redis,则必须在使用完毕销毁它,避免被子进程继承使用。

  • 暂无评论
phpcreeper

去掉了初始化redis实例的主进程代码【即去掉了图1中第22~25行代码】之后,发现图示诸如带冒号的诡异数据消失了,但是依然会出现不同的客户端读取到多条相同的数据,这个现象正常吗? 或者代码的编写逻辑还存在问题? 谢谢~~

  • 暂无评论
maq

你程序里的 incr 和 get 并不是一个原子操作,实际运行时可能出现多个进程分别执行了 incr,然后再分别执行 get,就会得到相同的数值。不过总体来看计数是不会错的。

事实上,incr 返回的就是自增之后的值,所以其实你根本不需要再 get 一次。

  • phpcreeper 2018-04-16

    非常感谢,查了下相关文档,一方面说get单命令执行是原子操作,但是这里的多进程get, 实际上存在你说的并发get,导致出现了相同的数值,既然是原子性操作的,不应该是针对并发而言吗? 理解的不透,能否解释下? 另一方面文档说incr是属于原子操作,修改代码后测试确实能如期工作。

  • maq 2018-04-16

    可能你对“原子操作”的理解不是很准确。

    redis 所有的单个命令都是原子的,因为 redis server 本身就是单线程的,所有所谓的“并发请求”到了 redis server 这里都是串行操作,一个一个执行,所以不会有互相的干扰。

    但是你的程序是先发送一个 incr 命令,再发送一个 get 命令,如果把这两个命令当作一个“操作”来看待的话,它就不是“原子操作”了,因为它们在 redis server 上执行的时候很可能中间被另外一个命令插队了。

  • phpcreeper 2018-04-17

    @3346:确实我理解的有偏差, 非常感谢~

年代过于久远,无法发表回答
×
🔝