遇到一个奇怪的问题,在 php 中使用 workerman 或者传统 pcntl_fork 的开启子进程时 大约十几分钟就会出现一段异常报错 protocol error, got 'u' as reply type byte 初步诊断是redis提示的 大致意思是 协议错误,得到'u'作为回复类型字节 。
异常信息
protocol error, got 'u' as reply type byte
通过代码排查以及报错提示初步判断是redis的问题
原因分析
传统 cli 下不会出现这个问题,只有 workerman 下以及 pcntl_fork 的开启子进程时 十几分钟后才会出现。
已知 workerman 底层使用的也是 pcntl_fork 我们直接分析这个函数。
pcntl_fork 函数 先创建主进程然后在根据需要创建N个子进程,而redis使用 单例模式 或者使用 static 来进行保存连接对象时候并且在主线程内有创建这个连接,那么就会出现以上 protocol error, got 'u' as reply type byte 错误 这种异常一般称为进程之间共享连接导致的。
那么我们只需要解决进程之间共享连接这个问题就可以解决 protocol error, got 'u' as reply type byte 错误。
解决方案
主要原理是子进程单独一个redis连接,不与其他进程共享。
方案一
在子进程中初始化掉redis的单例模式保存变量
方案二
我们只需要在主进程内不创建redis连接或者不使用 单例模式 或者 static 即可
方案三
在子进程中单独创建redis连接对象
三种方案推荐使用第一种方案,以上就是关于程序中提示 protocol error, got 'u' as reply type byte 错误的解决方案