PHP Session会话无法保存到Memcached 读写失败的解决办法
之前搬主题有介绍过将PHP Session会话保存到Memcached加快WordPress站点的访问速度。但…
之前搬主题有介绍过将PHP Session会话保存到Memcached加快WordPress站点的访问速度。但是有的小伙伴开始和我反馈,站点的错误日志里面老是提示无法保存法保存到Memcached 读写失败等提示。这里搬主题就给出相应的解决办法给到大家进行参考。
如何保存PHP Session会话到Memcached加快WordPress站点的访问速度?可以查看搬主题原来的文章
一、无法读取及无法写入缩的提示
如果有小伙伴经常查看自己站点的错误日志的话,类似这样的情况就会有如下提示:
PHP Warning: session_start(): Failed to read session data: memcached (path: 127.0.0.1:11211) in /home/banzhuti.com/www/wp-content/themes/xxx/xx.php on line 23
PHP Warning: session_start(): Failed to write session lock: SYSTEM ERROR in /home/banzhuti.com/www/wp-content/themes/xxx/xx.php on line 23
上面的提示的意思就是说PHP Session会话无法写入锁,也无法从memcached中读取会话数据
这样的提示会非常多,明明已经设置了PHP Session会话的保存路径是 127.0.0.1:11211
,为什么还提示错误呢?
二、PHP Session会话存在的影响
1、什么是PHP会话
PHP中的会话允许你存储关于一个特定请求的任意数据,并将这些数据传递给同一访问者的后续请求。这使得开发人员可以存储诸如购物车项目、认证会话和其他许多东西。
默认情况下,这些数据被存储在Web服务器的磁盘上,有一个唯一的会话标识符。这个标识符在每次请求时都会通过一个叫PHPSESSID的HTTP cookie(或GET/POST变量)来传递,这使得PHP可以将同一访问者的未来请求与现有的会话联系起来。
2、Sessions会话的问题
记住,一个PHP会话将产生一个唯一的标识符,将访问者与他们的会话数据联系起来。想一想这个问题吧。
这意味着,当使用会话时,每个访问者的标识符将迫使他们的所有请求都是唯一的,这给全页面缓存插件和服务带来了巨大的问题,因为如果请求是唯一的,他们根本无法提供相同的缓存数据。
因此,如果你在每个请求中都提前调用session_start(),最好的情况是你的缓存解决方案会简单地忽略,并且从不缓存这些请求。最坏的情况是–它将单独缓存这些请求,这意味着如果有1000个访问者打开了你的主页,你现在有1000个相同页面的不同缓存副本。这可能会导致其他更有价值的缓存数据被驱逐,以腾出空间给这些无稽之谈。
不过,仔细想想,更糟糕的情况是,如果你的缓存插件将这些请求缓存在同一个缓存密钥下,完全忽略了会话的存在。这将是非常不安全的,因为有可能一个用户收到为另一个用户生成的缓存页面。
3、基于文件的会话和锁定
PHP中会话的另一个问题是,默认情况下它们使用本地文件系统来存储所有会话数据。
这意味着会话对于跨越多个Web服务器的WordPress项目来说是一个大忌,除非你让相同的IP总是在负载均衡器层面上用IP散列来攻击同一Web服务器。但那是一种黑客行为,因为你可能需要把服务器下线来进行硬件升级,从而把所有的会话数据都带下来。
人们也可能认为磁盘IO最终会成为一个瓶颈,但会话文件通常太小,不会在磁盘上产生那样的负载,特别是SSD,而且硬件上有足够的空间用于内存中的磁盘页面缓存。
独占锁
但是,还有一个问题! 当你在PHP中调用session_start()时,运行你的代码的进程将获得该会话文件的独占锁,这意味着任何其他进程在获得类似的锁之前,必须等待该锁被释放。
所以这里有一个简单的场景。让我们假设你有一个愚蠢的备份插件,你在你的wp-admin中点击了那个按钮,这个按钮发射了一个需要30分钟才能加载的请求,而你在这个请求中传递了你的会话标识符。
这将催生一个PHP进程,它将获得一个对你的会话文件的独占锁,并开始备份30分钟的东西……
在你等待的时候,你决定访问你网站上一个完全不同的页面,同样,你的会话标识符与该请求一起被传递,产生了另一个具有相同会话的PHP进程。现在这个进程将试图获得同一个文件的独占锁,但它必须等待第一个进程释放它。
这时你有点沮丧,因为你的主页没有加载,所以你点击了刷新,产生了第三个具有相同会话标识符的PHP进程,它也将等待第一个进程释放锁。
现在你更沮丧了,所以你又按了几次刷新按钮,产生了第四、第五和第六个PHP进程,都在等待那个备份请求释放锁。
假设你的 web 服务器被配置为最多 8 个同时进行的 PHP 进程,你只需要再试几次就可以使服务器对所有人完全没有反应,直到备份任务完成。
你不会经常看到这种情况,特别是在较小的网站上,但当你看到它时,它不是很明显,而且很难调试。
WordPress不使用PHP会话
值得注意的是,WordPress Core并不使用本地的PHP会话。相反,它在很大程度上依赖于cookie进行认证,并在数据库中存储任何关于认证会话的额外信息。这意味着,如果你在你的WordPress网站上看到一个PHPSESSID cookie,它来自你的主题或一个插件,不幸的是,有太多的WordPress插件在使用PHP会话,而且更可悲的是,它们中的大多数都做错了。
当你发现这样一个插件时,为了你的WordPress的性能,你能做的最好的事情就是不使用它。
但是,如果它提供的一些功能对你的业务来说是必不可少的,而且没有其他可用的功能,那么与该插件的作者取得联系并要求他们解决这些问题将是一个好主意。
如果你是一个正在开发这样一个插件的开发者,而你又想不出在不使用会话的情况下提供同样功能的方法,那么要记住的基本规则是:只有在必要时才初始化会话,而且要尽可能晚。如果有必要,你也可以研究一下使用session_write_close()。
三、解决办法
一般这种报错情况是会话保存在Memcached才会出现的,那么我们的解决办法有如下几种
1、保存会话在硬盘上
打开站点的php.ini文件,这里以CyberPanel面板为例,登陆后,找到里面的PHP高级设置,选择对应的PHP版本,比如站点使用的PHP程序是7.4,那么就选择7.4
然后查找 session.save_handler
,在后面的等号输入 files
(一般默认的就是在硬盘上),然后保存即可,结果如下
但因为本身保存在硬盘上,读取速度取决于硬盘的速度,肯定比不上内存里读取速度,因此会导致站点慢一些。
2、保存会话在Redis
继续如上,打开php.ini文件,输入redis就行了,当然不要忘记了在下面输入 session.save_path = "127.0.0.1:6379"
,最终效果如下
因为Redis是没有锁的的说法,因此可以拿来用。但意味着你整个站点的对象存储也要改为Redis。
3、搬主题推荐的方法
如果站点使用的是Memcached,也不想改,又要速度,那么可以使用搬主题推荐的方法。在php.ini文件中查找
session.lazy_write
这里是默认开启的,将其前面的冒号去除,然后在后面改为Off,改完后如下
改完后进行保存然后重启PHP服务哦!
同时登陆主机的SSH,先查找Memcached配置文件在哪里,输入如下命令
find / -name memcached.ini
然后找到了对应PHP的版本文件如下
比如这里搬主题的路径为 /usr/local/lsws/lsphp74/share/doc/memcached/memcached.ini
然后进行编辑,输入如下命令进入编辑
vi /usr/local/lsws/lsphp74/share/doc/memcached/memcached.ini
然后将memcached.sess_locking注释去掉,后面改为Off,改好后如下
保存后,输入下面的命令进行Memcached服务重启
systemctl restart memcached.service
接下来就不会报错了
这里解释一下,session.lazy_write默认情况下设置是开启的,意味着session数据只在发生变化时才写入。当memcached.sess_locking默认开的话,会话文件将被锁定以在脚本执行期间进行读/写操作。脚本执行结束时释放锁定。因为这两个开启会找PHP会话大量的等待,然后导致速度变慢,因此关闭即可。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 wper_net@163.com 删除。
还没有任何评论,赶紧来占个楼吧!