欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解PHP解決守護(hù)進(jìn)程Redis假死

 更新時(shí)間:2021年06月04日 09:19:07   作者:李留廣  
公司業(yè)務(wù)有一個(gè)常駐后臺(tái)運(yùn)行的守護(hù)進(jìn)程。在這個(gè)守護(hù)進(jìn)程當(dāng)中使用了 Redis List 結(jié)構(gòu)保存業(yè)務(wù)數(shù)據(jù)進(jìn)行隊(duì)列消費(fèi)。結(jié)果運(yùn)行過(guò)程中,有時(shí)候半個(gè)月,有時(shí)候幾個(gè)月就會(huì)突然不再消費(fèi)隊(duì)列里面的數(shù)據(jù)。我們發(fā)現(xiàn)進(jìn)行心中檢測(cè)之后,程序的穩(wěn)定性大大提高。

一、一個(gè)簡(jiǎn)單的守護(hù)進(jìn)程示例

<?php
$redis = new \Redis();
$redis->connect('localhost', 6379);
$redis->auth('xxxxx'); // Redis 密碼如果沒(méi)有設(shè)置為空字符串。
$redis->select(1);

$queueKey    = 'redis_queue_services_key';     // 業(yè)務(wù)數(shù)據(jù)隊(duì)列。
$queueIngKey = 'redis_queue_services_ing_key'; // 處理中的隊(duì)列。

try {
    while (true) {
        $element = $redis->bRPopLPush($queueKey, $queueIngKey, 60);
        if ($element) {
            $data = json_decode($element, true);
            /**
             *
             ...... 此處省略業(yè)務(wù)邏輯 ......
             *
             */
        } else {
            usleep(100000); // 睡眠 0.1 秒。
        }
    }
} catch (\Exception $e) {
    exit("Error:{$e->getMessage()}");
}

這段代碼我們很容易看懂。

它就是通過(guò)Redis的阻塞方法bRPopLPush循環(huán)從 Redis 隊(duì)列中取出數(shù)據(jù)并處理。如果沒(méi)有取到數(shù)據(jù)就休眠一秒。之所以休眠是為了保證 CPU 能得到充分的利用。因?yàn)?,我們已?jīng)使用了阻塞方法阻塞 60 秒。所以,這個(gè)位置休眠與否并不重要。

當(dāng)我們的業(yè)務(wù)出現(xiàn)任何錯(cuò)誤,我們通過(guò)try catch進(jìn)行異常捕獲然后將錯(cuò)誤信息直接輸出并退當(dāng)前腳本。

博主寒冰第一次編寫(xiě)常駐后臺(tái)運(yùn)行的守護(hù)進(jìn)程時(shí),就是如上這種方式寫(xiě)的代碼。結(jié)果,這段代碼運(yùn)行到 30s 的時(shí)候報(bào)錯(cuò)了。提示我們 socket 流超時(shí)。于是我在這個(gè)腳本頭部加了如下代碼:

ini_set('default_socket_timeout', -1);

這樣我們的PHP就不會(huì)主動(dòng)段掉我們與 Redis 的 socket 連接了。

但是,好景不長(zhǎng)。過(guò)了一段時(shí)間,大概半個(gè)月吧。運(yùn)維同學(xué)告訴我 Redis 隊(duì)列的數(shù)據(jù)出現(xiàn)了未消費(fèi)的情況。然后,我查看了消費(fèi)日志。的確沒(méi)有產(chǎn)生新的消費(fèi)日志。因?yàn)槲矣幸粋€(gè)習(xí)慣,每個(gè)消費(fèi)消費(fèi)的時(shí)候都會(huì)把成功消費(fèi)的日志寫(xiě)到文件中。消費(fèi)失敗的也寫(xiě)入日志文件中。這樣,我就知道失敗的具體原因。

但是,這次我真的沒(méi)有發(fā)現(xiàn)有任何的錯(cuò)誤發(fā)生。

  • 常駐后臺(tái)進(jìn)程處理存活狀態(tài)。并沒(méi)有變成孤兒進(jìn)程。
  • 常駐后臺(tái)進(jìn)程內(nèi)存也沒(méi)有出現(xiàn)泄漏。
  • 系統(tǒng) CPU/內(nèi)存 資源都處理正在狀態(tài)。
  • 系統(tǒng)打開(kāi)的句柄資源也是低消狀態(tài)。
  • 帶寬也處理低消狀態(tài)。
  • 其它常駐進(jìn)程也處理正常消費(fèi)的工作狀態(tài)。也就排除了 Redis 故障的問(wèn)題。

我當(dāng)時(shí)也懷疑過(guò)是不是像MySQL一樣常時(shí)間連接不進(jìn)行任何操作,服務(wù)器端會(huì)主動(dòng)斷開(kāi)連接。但是,MySQL 服務(wù)器端主動(dòng)段掉連接會(huì)提示:MySQL server has gone away的錯(cuò)誤。但是,我們的 Redis 服務(wù)器端沒(méi)有給我們報(bào)任何錯(cuò)誤信息呀。

我們公司用的是阿里云的 Redis 產(chǎn)品。我懷疑是不是 Redis 版本太低造成的這個(gè)隱性 BUG。于是,我們將阿里云的 Redis 服務(wù)升級(jí)到了阿里云支持的最新版本。

結(jié)果還是失敗了。我們的 Redis 還是假死了。或者說(shuō)我們的 Redis 處于偽活狀態(tài)。

你認(rèn)為 Redis 活著,其實(shí)它早已經(jīng)死了。你認(rèn)為 Redis 死了,但是它卻沒(méi)有死亡的特征。

最后,我冷靜下來(lái)。

我假定此時(shí)的 Redis 已經(jīng)死了。只是沒(méi)有告訴客戶(hù)端而已。那么我只需要每次檢測(cè)一下 Redis 連接是否存活就好了。

于是,我翻看了 Redis 的 API。發(fā)現(xiàn)它提供了一個(gè)ping()的方法來(lái)檢測(cè)連接是否存活。

二、一個(gè)不再假死(偽活)的 Redis 常駐進(jìn)程示例

<?php

$redis = new \Redis();
$redis->connect('localhost', 6379);
$redis->auth('xxxxx'); // Redis 密碼如果沒(méi)有設(shè)置為空字符串。
$redis->select(1);

$queueKey    = 'redis_queue_services_key';     // 業(yè)務(wù)數(shù)據(jù)隊(duì)列。
$queueIngKey = 'redis_queue_services_ing_key'; // 處理中的隊(duì)列。

try {
    while (true) {
        $element = $redis->bRPopLPush($queueKey, $queueIngKey, 60);
        if ($element) {
            $data = json_decode($element, true);
            /**
             *
             ...... 此處省略業(yè)務(wù)邏輯 ......
             *
             */
        } else {
            $pong = $redis->ping();
            if ($pong != '+PONG') {
                throw new \Exception('Redis ping failure!', 500);
            }
            usleep(100000); // 睡眠 0.1 秒。
        }
    }
} catch (\Exception $e) {
    exit("Error:{$e->getMessage()}");
}

通過(guò)代碼對(duì)比,我們?cè)诘谝话娲a的基礎(chǔ)上加了如下代碼:

$pong = $redis->ping();
if ($pong != '+PONG') {
    throw new \Exception('Redis ping failure!', 500);
}

我們向 Redis 服務(wù)器發(fā)送ping的時(shí)候,服務(wù)器會(huì)返回+PONG字符串。當(dāng)然,這個(gè)是 Redis 擴(kuò)展封裝過(guò)的方法。真正的 ping 是不會(huì)有 + 號(hào)的。

當(dāng)我們每次 ping 的時(shí)候,Redis 服務(wù)器就會(huì)認(rèn)為我們的 Redis 客戶(hù)端連接處于存活狀態(tài)。就不會(huì)斷掉我們的連接了。

把代碼進(jìn)行改造之后,假死頭痛的問(wèn)題再也沒(méi)出現(xiàn)了。

以上就是詳解PHP解決守護(hù)進(jìn)程Redis假死的詳細(xì)內(nèi)容,更多關(guān)于PHP解決守護(hù)進(jìn)程Redis假死的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • php 抽象類(lèi)的簡(jiǎn)單應(yīng)用

    php 抽象類(lèi)的簡(jiǎn)單應(yīng)用

    我想博客中的 文章列表和單個(gè)的文章閱讀 統(tǒng)一起來(lái),我覺(jué)得除了sql查詢(xún)語(yǔ)句結(jié)構(gòu)不同,HTML代碼不同,其它也就一樣。不過(guò)話說(shuō)回來(lái),這兩個(gè)都是主要功能,所以這的確有點(diǎn)不適合,不過(guò)昨晚讀了一點(diǎn)設(shè)計(jì)模式,好歹得寫(xiě)點(diǎn)啥好。
    2011-09-09
  • PHP和Mysql中轉(zhuǎn)UTF8編碼問(wèn)題匯總

    PHP和Mysql中轉(zhuǎn)UTF8編碼問(wèn)題匯總

    這篇文章主要總結(jié)了PHP頁(yè)面和Mysql數(shù)據(jù)庫(kù)的轉(zhuǎn)UTF8編碼問(wèn)題,需要的朋友可以參考下
    2015-10-10
  • php生成酷炫的四個(gè)字符驗(yàn)證碼

    php生成酷炫的四個(gè)字符驗(yàn)證碼

    可以生成隨機(jī)顏色、干擾線條元素、干擾點(diǎn)元素的php驗(yàn)證碼,這篇文章主要介紹了php生成酷炫的四個(gè)字符驗(yàn)證碼的編寫(xiě)方法,感興趣的小伙伴們可以參考一下
    2016-04-04
  • PHP 配置open_basedir 讓各虛擬站點(diǎn)獨(dú)立運(yùn)行

    PHP 配置open_basedir 讓各虛擬站點(diǎn)獨(dú)立運(yùn)行

    好幾年前,我在抱怨Apache運(yùn)行PHP的安全性不行,只要一個(gè)站點(diǎn)被人拿下,服務(wù)器上的其他站點(diǎn)就會(huì)跟著遭殃。
    2009-11-11
  • PHP調(diào)用外部程序的方法解析

    PHP調(diào)用外部程序的方法解析

    這篇文章主要介紹了PHP調(diào)用外部程序的方法解析,對(duì)此感興趣的同學(xué),可以多研究一下
    2021-04-04
  • pdo中使用參數(shù)化查詢(xún)sql

    pdo中使用參數(shù)化查詢(xún)sql

    在使用參數(shù)化查詢(xún)的情況下,數(shù)據(jù)庫(kù)服務(wù)器不會(huì)將參數(shù)的內(nèi)容視為SQL指令的一部份來(lái)處理,而是在數(shù)據(jù)庫(kù)完成 SQL 指令的編譯后,才套用參數(shù)運(yùn)行,因此就算參數(shù)中含有具破壞性的指令,也不會(huì)被數(shù)據(jù)庫(kù)所運(yùn)行。
    2011-08-08
  • PHP+JS三級(jí)菜單聯(lián)動(dòng)菜單實(shí)現(xiàn)方法

    PHP+JS三級(jí)菜單聯(lián)動(dòng)菜單實(shí)現(xiàn)方法

    這篇文章主要介紹了PHP+JS三級(jí)菜單聯(lián)動(dòng)菜單實(shí)現(xiàn)方法,涉及JavaScript動(dòng)態(tài)控制頁(yè)面樣式及PHP數(shù)據(jù)庫(kù)操作相關(guān)技巧,需要的朋友可以參考下
    2016-02-02
  • 基于PHP實(shí)現(xiàn)的事件機(jī)制實(shí)例分析

    基于PHP實(shí)現(xiàn)的事件機(jī)制實(shí)例分析

    這篇文章主要介紹了基于PHP實(shí)現(xiàn)的事件機(jī)制,實(shí)例分析了事件機(jī)制的原理及php中debug_backtrace函數(shù)完成事件機(jī)制的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-06-06
  • PHP Laravel框架緩存操作介紹

    PHP Laravel框架緩存操作介紹

    緩存是使Web應(yīng)用程序快速運(yùn)行的重要工具。這很容易實(shí)現(xiàn),但很難做到正確。如何使用Laravel的內(nèi)置系統(tǒng)實(shí)現(xiàn)緩存,該系統(tǒng)支持Memcached和Redis等多種后端
    2022-09-09
  • php實(shí)現(xiàn)的后臺(tái)表格分頁(yè)功能示例

    php實(shí)現(xiàn)的后臺(tái)表格分頁(yè)功能示例

    這篇文章主要介紹了php實(shí)現(xiàn)的后臺(tái)表格分頁(yè)功能,涉及php針對(duì)數(shù)據(jù)庫(kù)的連接、查詢(xún)、刪除、動(dòng)態(tài)生成表格等相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10

最新評(píng)論