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

詳解PHP解決守護進程Redis假死

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

一、一個簡單的守護進程示例

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

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

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

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

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

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

博主寒冰第一次編寫常駐后臺運行的守護進程時,就是如上這種方式寫的代碼。結果,這段代碼運行到 30s 的時候報錯了。提示我們 socket 流超時。于是我在這個腳本頭部加了如下代碼:

ini_set('default_socket_timeout', -1);

這樣我們的PHP就不會主動段掉我們與 Redis 的 socket 連接了。

但是,好景不長。過了一段時間,大概半個月吧。運維同學告訴我 Redis 隊列的數(shù)據(jù)出現(xiàn)了未消費的情況。然后,我查看了消費日志。的確沒有產(chǎn)生新的消費日志。因為我有一個習慣,每個消費消費的時候都會把成功消費的日志寫到文件中。消費失敗的也寫入日志文件中。這樣,我就知道失敗的具體原因。

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

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

我當時也懷疑過是不是像MySQL一樣常時間連接不進行任何操作,服務器端會主動斷開連接。但是,MySQL 服務器端主動段掉連接會提示:MySQL server has gone away的錯誤。但是,我們的 Redis 服務器端沒有給我們報任何錯誤信息呀。

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

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

你認為 Redis 活著,其實它早已經(jīng)死了。你認為 Redis 死了,但是它卻沒有死亡的特征。

最后,我冷靜下來。

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

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

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

<?php

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

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

try {
    while (true) {
        $element = $redis->bRPopLPush($queueKey, $queueIngKey, 60);
        if ($element) {
            $data = json_decode($element, true);
            /**
             *
             ...... 此處省略業(yè)務邏輯 ......
             *
             */
        } 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()}");
}

通過代碼對比,我們在第一版代碼的基礎上加了如下代碼:

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

我們向 Redis 服務器發(fā)送ping的時候,服務器會返回+PONG字符串。當然,這個是 Redis 擴展封裝過的方法。真正的 ping 是不會有 + 號的。

當我們每次 ping 的時候,Redis 服務器就會認為我們的 Redis 客戶端連接處于存活狀態(tài)。就不會斷掉我們的連接了。

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

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

相關文章

  • php 抽象類的簡單應用

    php 抽象類的簡單應用

    我想博客中的 文章列表和單個的文章閱讀 統(tǒng)一起來,我覺得除了sql查詢語句結構不同,HTML代碼不同,其它也就一樣。不過話說回來,這兩個都是主要功能,所以這的確有點不適合,不過昨晚讀了一點設計模式,好歹得寫點啥好。
    2011-09-09
  • PHP和Mysql中轉UTF8編碼問題匯總

    PHP和Mysql中轉UTF8編碼問題匯總

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

    php生成酷炫的四個字符驗證碼

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

    PHP 配置open_basedir 讓各虛擬站點獨立運行

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

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

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

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

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

    PHP+JS三級菜單聯(lián)動菜單實現(xiàn)方法

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

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

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

    PHP Laravel框架緩存操作介紹

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

    php實現(xiàn)的后臺表格分頁功能示例

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

最新評論