当前位置:首页 » 《随便一记》 » 正文

Ununbu上Redis的安装以及php+redis应用中常见错误的解决方法

21 人参与  2024年04月26日 12:35  分类 : 《随便一记》  评论

点击全文阅读


    以前一直喜欢使用Centos服务器,这次不得不用Ubuntu,不过觉得Ubuntu用起来也挺舒服的,特别是在安装一些软件的时候安装完毕连启动都省了,安装完即开始使用,感觉很方便。

一、Ununbu 上 Redis 的安装

    不过在安装redis的时候怪了竟然报错:E: Unable to locate package redis,还以为是apt-get源中没有对应的redis,虽然想想应该不可能,但在网上找到相关的提示也说是要更新源,比如用阿里云的源,比如这篇文章:Ubuntu修改apt-get软件源,解决E: Unable to locate package redis错误 - 简书 (Ubuntu修改apt-get软件源,解决E: Unable to locate package redis错误) 。但我修改后依然不行。我的ubuntu是16.04版本。

1. 关于 Unable to locate package redis 问题

    后来各种查找资料才知道只是因为redis的包名叫做:redis-server,Ubuntu安装之后的配置文件都在/etc/应用/中。包括nginx,mysql等,统一、规范很好使用。安装过程如下:

#提示E: Unable to locate package redisroot@us12:/opt/downloads# apt-get install redisReading package lists... DoneBuilding dependency tree       Reading state information... DoneE: Unable to locate package redis#使用redis-serverroot@us12:/etc/apt# apt-get install redis-serverReading package lists... DoneBuilding dependency tree       Reading state information... DoneThe following package was automatically installed and is no longer required:libopts25Use 'apt autoremove' to remove it.The following additional packages will be installed:libjemalloc1 redis-toolsSuggested packages:ruby-redisThe following NEW packages will be installed:libjemalloc1 redis-server redis-tools0 upgraded, 3 newly installed, 0 to remove and 112 not upgraded.......Processing triggers for systemd (229-4ubuntu21.21) ...root@us12:/etc/apt# ps -ef | grep redisredis    28135     1  0 11:23 ?        00:00:00 /usr/bin/redis-server 127.0.0.1:6379root     28173 28670  0 11:23 pts/0    00:00:00 grep --color=auto redis

二、Redis 使用中常见的各种错误及解决办法

1. RedisException with message read error on connection问题

    关于redis的问题:RedisException with message read error on connection。最近碰到在REDIS执行一步get操作的时候报出错误:Uncaught RedisException: read error on connection,感觉不可理解,REDIS连接没有发现问题,但是就是get失败,在redis的日志中也没有找到慢查询,说明这个报错也不是超时。连接没有发生问题,又没有超时,什么会读失败呢?

    在网上找了些答案,但基本都是千遍一律地认为是这行配置的问题:

default_socket_timeout = 60; 

     都建议把它改成-1.不超时

ini_set('default_socket_timeout', -1);  //在php程序中修改default_socket_timeout = -1;            //或者修改配置文件

    原因都写着:由于redis扩展也是基于php 的socket方式实现,因此该参数值同样会起作用。但想想如果是这个配置的问题的话,那意思就是说请求redis读时超时了是不是?可这个配置的单位是秒啊!你能超60秒?如果一个请求超过了60秒还没有执行成功,这个值改大了又有什么意思?不知道网上碰到这个问题并写着按这个方法解决的朋友是不是后面再也没有碰到这个问题。
但我就是怀疑是这个地方的问题!

    在网上找了些相关的资料,也翻墙出去看了一些。看到了这么一篇讨论,里面有一个回答:

 PHP Redis timeout, read error on connection? - Stack Overflow

     After a lot of study of articles and doing my own strace's of redis and php, it seemed the issue was easily fixed by this solution. The main issue in my use case was that redis server is not able to fork a process towards saving the in-memory writes to the on-disk db.
    I have left all the timeout values in php.ini and redis.conf as they were without making the hacky changes suggested and then tried the above solution alone, and this issue 'read error on connection' that was unfixable using all the suggestions around changing timeout values across php and redis conf files went away.
    I also saw some suggestions around increasing limit on file descriptors to 100000 etc. I am running my use case on a cloud server with file descriptor limit at 1024 and my use case runs even with that limit perfectly.

    其中提到的 by this solution 链接到了这篇文章的这个位置:从上面的说法来看这个是可以解决这个问题,我还没有测试验证。文章链接    https://groups.google.com/forum/#!msg/redis-db/3Eh2hhsXQ1g/_nAzuK--nYYJ  提到的解决方法如下:

> Ok further investigations showed that probably this is due to 
> /proc/sys/vm/overcommit_memory 
> If it's zero in your system try to set it to 1 or 2 and check what 
> happens. I'm going to try this in few hours. 

echo 1 > /proc/sys/vm/overcommit_memory 

works perfectly! So the problem was with the kernel _estimating_ how 
much memory would the forked process need. Echoing "1" as I understand 
disables the check and enables the process to fork. 

Since "0" is default of overcommit_memory, perhaps the issue is much 
more common on Linux boxes. It also looks like MacOSX is free of this 
issue. 

If confirmed, it would be nice to have it added to the FAQ. 
Great job and many thanks again 

2. 引申了解一下关于内核参数overcommit_memory 各值意义:     

overcommit_memory文件指定了内核针对内存分配的策略,其值可以是0、1、2。

0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。 
1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2, 表示内核允许分配超过所有物理内存和交换空间总和的内存

#修改方法:vim  /etc/sysctl.conf                                                        vm.overcommit_memory=1#或者sysctl vm.overcommit_memory=1#或者echo 1 > /proc/sys/vm/overcommit_memory

3. Uncaught RedisException: protocol error, got 'u' as reply type byte问题

    最近在redis的处理上遇见了两个蛋痛的问题,一个就是之前有篇文章提过的:Uncaught RedisException: read error on connection。目前服务器上还是偶尔出现,我们的服务器构架里有30多台WEB,70多个redis实例,这个read error on connection是每台服务器上都会有,但是极少。零星地有报。网上说的各种原因我们也尝试过了,问题依旧没有解决。

    今天在30多台服务器中有一台服务器像抽风了一样,在25分钟报了60几条错误,错误如下:

Redis.php:Uncaught RedisException: protocol error, got 'u' as reply type byte...Redis.php:Uncaught RedisException: protocol error, got '°' as reply type byte...Redis.php:Uncaught RedisException: protocol error, got '<92>' as reply type byte...

     都是报redis的连接类在连接redis时发生协议错误有一些非还的的返回内容。到底是发生了什么异常?

     首先这些redis服务器每台WEB的连接机会都是一样的,如果是redis的问题,那么肯定就不只这一台服务器发生异常。而应该在其它服务器上也同样会出现。

    另外经过查看报错时大多是同一个地方,但也不全是一个地方。读取的不只是一台redis.即报错的这个WEB服务器有时在请求这台REDIS报错,有时请求那台报错。这样来看问题是出现在此WEB服务器上,但WEB服务器上究竟发生了什么呢?感觉无从下手。有怀疑是php使用的redis扩展问题:我们使用的php7,redis扩展使用的是phpredis3.1。

redis Server上使用的是redis_version:3.2.8 

    网上有一些说的解决办法:比如关闭protected-mode,我们这项采用的就是关闭的。还有说要注释掉bind配置项,我也不觉得是这项的问题,另外这项如果注释掉的话,风险很大。

    线上的redis肯定要求内网访问,且绑定到指定IP地址。也有提议更换redis扩展的事,这个变更太大。不同的扩展的调用方法不尽相同。修改成本很高,且目前没有哪里得到证实此项是问题所在。

    目前出现这种问题时,我重启一下php后就不再出现,但仍不知道问题所在。

4. Uncaught RedisException: Redis is LOADING the dataset问题

    关于redis报错 Uncaught RedisException: Redis is LOADING the dataset (日志:scheduled to be closed ASAP for overcoming of output buffer limits.)

    突然收到服务器报警,看了一下程序日志,redis读取数据时报错Uncaught RedisException: Redis is LOADING the dataset,这块业务的redis架构是1主3丛,通过对主库的info信息查看,发现从库有时直接显示down.而在服务器的表象上,主从链接也会每隔1分钟左右就断开一次,导致需要重新同步,主库上看到每隔一分钟主库就会进行一次bgsave操作。

查看主库日志如下:

26543:M 10 Jun 00:48:21.566 * Slave 192.168.168.90:9736 asks for synchronization26543:M 10 Jun 00:48:21.566 * Full resync requested by slave 192.168.168.90:973626543:M 10 Jun 00:48:21.113 * Starting BGSAVE for SYNC with target: disk26543:M 10 Jun 00:48:21.557 * Background saving started by pid 583026543:M 10 Jun 00:48:21.566 * Waiting for end of BGSAVE for SYNC26543:M 10 Jun 00:49:09.178 # Client id=343957 addr=192.168.168.90:27081 fd=2051 name= age=48 idle=48 flags=S db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=5473 oll=8202 omem=268437704 events=rw cmd=psync scheduled to be closed ASAP for overcoming of output buffer limits.26543:M 10 Jun 00:49:09.230 # Connection with slave 192.168.168.90:9736 lost. 

     日志中显示错误: scheduled to be closed ASAP for overcoming of output buffer limits.此项报错与redis配置文件中的client-output-buffer-limit slave项配置有关系。redis中的英文配置项注释如下:

# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>## A client is immediately disconnected once the hard limit is reached, or if# the soft limit is reached and remains reached for the specified number of# seconds (continuously).# So for instance if the hard limit is 32 megabytes and the soft limit is# 16 megabytes / 10 seconds, the client will get disconnected immediately# if the size of the output buffers reach 32 megabytes, but will also get# disconnected if the client reaches 16 megabytes and continuously overcomes# the limit for 10 seconds.## By default normal clients are not limited because they don't receive data# without asking (in a push way), but just after a request, so only# asynchronous clients may create a scenario where data is requested faster# than it can read.## Instead there is a default limit for pubsub and slave clients, since# subscribers and slaves receive data in a push fashion.## Both the hard or the soft limit can be disabled by setting them to zero.client-output-buffer-limit normal 0 0 0client-output-buffer-limit slave 256mb 64mb 60client-output-buffer-limit pubsub 32mb 8mb 60

各项具体参数的意义:

class: 客户端种类,包括Normal,Slaves和Pub/Sub
Normal: 普通的客户端。默认limit 是0,也就是不限制。
Pub/Sub: 发布与订阅的客户端的。默认hard limit 32M,soft limit 8M/60s。
Slaves: 从库的复制客户端。默认hard limit 256M,soft limit 64M/60s。
hard limit: 缓冲区大小的硬性限制。
soft limit: 缓冲去大小的软性限制。
soft seconds: 缓冲区大小达到了(超过)soft limit值的持续时间。
client-output-buffer-limit参数限制分配的缓冲区的大小,防止内存无节制的分配,Redis将会做如下自我保护:
client buffer的大小达到了soft limit并持续了soft seconds时间,将立即断开和客户端的连接
client buffer的大小达到了hard limit,server也会立即断开和客户端的连接

    所以需要client-output-buffer-limit slave项的配置,将其改为 0 0 0 。重启主库即可解决这种由scheduled to be closed ASAP for overcoming of output buffer limits引起的Redis is LOADING the dataset问题。当然引起Redis is LOADING the dataset问题还有其它的原因,比如内存不足。导致使用SWAP,这样redis加载数据的性能会大大降低导致报错Redis is LOADING the dataset。


点击全文阅读


本文链接:http://zhangshiyu.com/post/100481.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1