解决ownCloud“事务文件锁定应配置为使用基于内存的锁定”错误+Docker环境处理方法

Posted by 橙叶 on Sat, Feb 3, 2018

很久之前就有人问我ownCloud安装完成后的一项警告:

[warningbox]事务文件锁定应配置为使用基于内存的锁定,而不是默认的基于慢速数据库的锁定。[/warningbox]

在后台管理页面是这样显示的:

原因分析

事务文件锁定

事务文件锁定功能的作用:保护文件在正常操作时不被损坏。具体地,这个功能能够防止多个用户操作同一文件(不使用类似Collabora Online的多人协作平台)时导致文件损坏或系统错误,比如修改一个文件夹中的文件,那么此时这个文件所处的文件夹就会被锁定,无法被重命名、移动等等,知道对该文件的修改完成。

由上面简单的介绍可知,这个功能需要不断存取文件夹的状态(锁定or未锁定)信息。这种情况下,内存缓存是最好的解决方案,如果没有配置内存缓存,ownCloud就会使用数据库来存取,效率会低很多。

错误原因

但是问题来了,明明配置了内存缓存,为什么仍然会有这样的提示信息?

翻阅了一下文档,看到了这样一句话:

[infobox]Memcached is a reliable old-timer for shared caching on distributed servers. It performs well with ownCloud with one exception: it is not suitable to use with Transactional File Locking. This is because it does not store locks, and data can disappear from the cache at any time. Given that, Redis is the best memory cache to use.

Memcached是分布式服务器上共享缓存的可靠的旧计时器。它与ownCloud运行良好,但有一个例外:它不适合与事务性文件锁定一起使用。这是因为它不存储锁,数据可以随时从缓存中消失。鉴于此,Redis是使用最好的内存缓存。[/infobox]

也就是说,我们常用的Memcached方式是无法用于文件锁的存储,解决方法就是更换成Redis。

[caption id=“attachment_3055” align=“alignnone” width=“1000”] Redis工作流程(图文无关)[/caption]

解决步骤(Linux)

首先要安装Redis以及相应的php扩展:
Ubuntu/Debian:
apt-get install redis-server php-redis
CentOS/Fedora/RedHat
yum install rh-php70-php-devel rh-redis32-redis
pecl install redis
在CentOS/Fedora/RedHat中与Ubuntu等不同,所安装的服务不会自动启动也不会随开机启动,所以通常下我们还需要执行下面的配置:
systemctl start rh-redis32-redis     #启动Redis
systemctl enable rh-redis32-redis    #配置Redis开机启动
确认Redis是否正在运行:
ps ax | grep redis
netstat -tlnp | grep redis
Redis开始运行后,启用相应php模块:
cat << EOF > /etc/opt/rh/rh-php70/php.d/20-redis.ini
; Redis php extension
extension=redis.so
EOF
你也可以手动在php.ini中添加以下内容,效果相同:
; Redis php extension
extension=redis.so
EOF

完成后,就可以重启Apache了。

接下来,在ownCloud的config/config.php文件中添加以下内容来为ownCloud启用Redis:

 'memcache.local' => '\OC\Memcache\Redis',
 'redis' => [
     'host' => 'localhost',
     'port' => 6379,
 ],
'memcache.locking' => '\OC\Memcache\Redis', //使用Redis来管理事务文件锁定

(如果没有最后一行的内容,即便使用Redis作为缓存,仍然会显示警告信息)

小规模地使用ownCloud,Redis和ownCloud实例一般都放在同一台主机上,所以也可以以Unix Socket的方式与Redis通信:

'memcache.local' => '\OC\Memcache\Redis',
'redis' => [
     'host' => '/var/run/redis/redis.sock',
     'port' => 0,
],
'memcache.locking' => '\OC\Memcache\Redis', //别忘了这句

添加完成后刷新ownCloud

解决步骤(Docker环境)

现在我已经很少专门搭建演示环境了,一般直接使用Docker来完成,不仅ownCloud和Nextcloud一键切换,而且容器即用即启,不影响宿主机上的服务,非常方便省时。

只有一个问题,官方提供的Docker镜像所使用的apt源并不完整,redis-server、php-redis一个也没有。经过一番研究,发现php扩展已经安装,只需要考虑Redis服务就行了。

一个可行的方法是更换apt源,不过还有一个更好的方法:与单独运行Redis的容器互联,这样也符合了Docker构建服务的习惯做法。

运行官方Redis镜像:

docker run --name redis-server -d redis

在运行ownCloud镜像时与Redis建立互联

docker run --name redis-server --link reids-server:redis -d owncloud:latest

如果此时ownCloud已存在,则要将Redis与ownCloud主动建立互联:

docker run --name redis-server --link owncloud:owncloud -d redis

如果ownCloud容器使用的不是默认网桥(例如使用docker-composer建立),就需要将Redis添加到相应网桥中:

docker run --name redis-server --network [网桥名] -d redis

修改ownCloud的配置文件,添加以下内容,注意“host"后面要填容器名或容器ID:

 'memcache.local' => '\OC\Memcache\Redis',
 'redis' => [
     'host' => 'redis',
     'port' => 6379,
 ],
'memcache.locking' => '\OC\Memcache\Redis',

完成后,刷新ownCloud页面,可以看到有关内存缓存和事务文件锁定的错误已经消失:



comments powered by Disqus