通過 Swoole\Table 實現 Swoole 多進程數據共用

来源:https://www.cnblogs.com/a609251438/archive/2020/04/24/12769695.html
-Advertisement-
Play Games

第三方存儲媒介 前面我們介紹了基於 Swoole 的 Process 及 Process\Pool 模塊在 PHP 中實現多進程管理,但是多進程模式下進程間是相互隔離的,無法共用數據和變數,即便是通過 global 定義的全局或超全局變數,也只是在所屬進程中有效,如果要在 Swoole 實現的多進程 ...


第三方存儲媒介

前面我們介紹了基於 Swoole 的 Process 及 Process\Pool 模塊在 PHP 中實現多進程管理,但是多進程模式下進程間是相互隔離的,無法共用數據和變數,即便是通過 global 定義的全局或超全局變數,也只是在所屬進程中有效,如果要在 Swoole 實現的多進程間共用數據,需要藉助第三方存儲媒介實現:

  • 資料庫:MySQL、MongoDB
  • 緩存:Redis、Memcached
  • 磁碟文件

但是這也會引入新的問題,多進程同時操作一條記錄或一個文件存在併發訪問問題,以資料庫操作為例,兩個進程可能會同時讀取一條數據,或者一個進程對某條記錄進行更新處理時,另一個進程也來讀取這條記錄併進行操作,會導致最終結果數據與預期不一致的情況,這個時候,我們就需要引入鎖的概念,當一個進程(比如進程A)對某個記錄進行寫操作時,對該記錄加鎖,這樣其它進程就無法操作該條記錄, 直到進程 A 事務提交再釋放這個鎖,讓其他進程可以進行操作。

記憶體共用

PHP 相關擴展

對於單機操作來說,除了這些第三方存儲媒介之外,還可以通過共用記憶體的方式實現進程間數據讀寫操作,有多個 PHP 擴展可以支持共用記憶體數據操作:

  • Semaphore 擴展:可通過該擴展包提供的 shm_get_var 和 shm_put_var 函數實現記憶體共用數據的讀寫操作;
  • Shmop 擴展:可通過該擴展包提供的 shmop_read 和 shmop_write 函數實現記憶體共用數據的讀寫操作;
  • APCu(APC User Cache)擴展:可通過該擴展包提供的 apc_fetch 和 apc_store 實現記憶體共用數據的讀寫操作。

Swoole Table

但是上述擴展要麼不支持鎖,要麼高併發時性能比較差,所以 Swoole 自己實現了一個共用記憶體讀寫工具 —— Swoole\Table,該工具是一個基於共用記憶體和鎖實現的高性能併發數據結構,可用於解決多進程/多線程數據共用和同步加鎖問題:

  • 性能強悍,單線程每秒可讀寫200萬次;
  • 應用代碼無需加鎖,內置行鎖自旋鎖,所有操作均是多線程/多進程安全,用戶層完全不需要考慮數據同步問題;
  • 支持多進程,可用於多進程之間共用數據;
  • 使用行鎖,而不是全局鎖,僅當 2 個進程在同一 CPU 時間,併發讀取同一條數據才會進行發生搶鎖。

Swoole\Table 支持以 Key-Value 方式讀寫,使用起來非常簡單:

<?php

// 初始化一個容量為 1024 的 Swoole Table
$table = new \Swoole\Table(1024);
// 在 Table 中新增 id 列
$table->column('id', \Swoole\Table::TYPE_INT);
// 在 Table 中新增 name 列,長度為 50
$table->column('name', \Swoole\Table::TYPE_STRING, 10);
// 在 Table 中新澤 score 列
$table->column('score', \Swoole\Table::TYPE_FLOAT);
// 創建這個 Swoole Table
$table->create();


// 設置 Key-Value 值
$table->set('student-1', ['id' => 1, 'name' => '學小君', 'score' => 80]);
$table->set('student-2', ['id' => 2, 'name' => '學院君', 'score' => 90]);

// 如果指定 Key 值存在則列印對應 Value 值
if ($table->exist('student-1')) {
    echo "Student-" . $table->get('student-1', 'id') . ':' . $table->get('student-1', 'name').":".
        $table->get('student-1', 'score') . "\n";
}

// 自增操作
$table->incr('student-2', 'score', 5);
// 自減操作
$table->decr('student-2', 'score', 5);

// 表中總記錄數
$count = $table->count();

// 刪除指定表記錄
$table->del('student-1');

  

此外 Swoole\Table 類還實現了迭代器介面,支持通過 foreach 進行遍歷。

在 Laravel 中使用 Swoole\Table

如果要在 Laravel 中集成 Swoole 使用 Swoole\Table,以 LaravelS 擴展包為例,首先要在配置文件 config/laravels.php 中定義 swoole_tables 配置項:

'swoole_tables'            => [
    'ws' => [ // 表名,會加上 Table 尾碼,比如這裡是 wsTable
        'size'   => 102400, //  表容量
        'column' => [ // 表欄位,欄位名為 value
            ['name' => 'value', 'type' => \Swoole\Table::TYPE_INT, 'size' => 8],
        ],
    ],
    ... // 還可以定義其它表
],

  

然後我們可以在代碼中通過swoole實例上的wsTable屬性訪問 SwooleTable:

class WebSocketService implements WebSocketHandlerInterface
{
    ...

    // 連接建立時觸發
    public function onOpen(Server $server, Request $request)
    {
        // 在觸發 WebSocket 連接建立事件之前,Laravel 應用初始化的生命周期已經結束,你可以在這裡獲取 Laravel 請求和會話數據
        // 調用 push 方法向客戶端推送數據,fd 是客戶端連接標識欄位
        Log::info('WebSocket 連接建立:' . $request->fd);
        app('swoole')->wsTable->set('fd:' . $request->fd, ['value' => $request->fd]);
        $server->push($request->fd, 'Welcome to WebSocket Server built on LaravelS');
    }

    // 收到消息時觸發
    public function onMessage(Server $server, Frame $frame)
    {
        foreach (app('swoole')->wsTable as $key => $row) {
            if (strpos($key, 'fd:') === 0 && $server->exist($row['value'])) {
                Log::info('Receive message from client: ' . $row['value']);
                // 調用 push 方法向客戶端推送數據
                $server->push($frame->fd, 'This is a message sent from WebSocket Server at ' . date('Y-m-d H:i:s'));
            }
        }
    }
    
    ...

}

  

然後我們參考在 Laravel 中集成 Swoole 實現 WebSocket 伺服器這篇教程從客戶端向 WebSocket 伺服器發起請求,即可在最新日誌文件中看到相應的日誌信息:

[2020-04-24 19:39:03] local.INFO: WebSocket 連接建立:1  
[2020-04-24 19:39:07] local.INFO: Receive message from client: 1

  




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一:構造方法的概念: 構造方法是一種特殊的方法,它是一個與類同名的方法。對象的創建就是通過構造方法來完成,其功能主要是完成對象的初始化。當類實例化一個對象時會自動調用構造方法。構造方法和其他方法一樣也可以重載。 二:構造方法的特殊性(反映在以下幾個方面): 1.構造方法作用: (1)構造出來一個類的 ...
  • 案例故事: Android車載測試過程中,客戶反饋低概率偶現高德地圖App啟動過程中, 出現了報錯:“高德地圖無法繼續運行”,客戶說只碰到過一次,後續再沒復現過, 測試經理安排我們負責壓測,反覆進行高德地圖打開關閉, 併在打開過程中,截一張圖,打開載入完畢後再截取一張圖, 測試經理希望自動化實現截取 ...
  • 基本if選擇結構 語法: if(條件){ ​ //條件為真執行 }條件為假執行大括弧外 案列: 1 if(javaScore>98){ 2 System.out.println("獎勵硬碟"); 3 } if-else選擇結構 語法: if(條件){ ​ //代碼塊1 }else{ ​ //代碼塊2 ...
  • 【準備環境】 python pycharm mysql 參考 https://www.cnblogs.com/xinhua19/p/12750611.html redis 參考https://www.cnblogs.com/xinhua19/p/12750659.html 【步驟】 1.打開pych ...
  • Python 代碼編輯器怎麼選?PyCharm、VS Code、Jupyter Notebook 都各有特色,Jupyter 適合做數據分析這些需要可視化的操作,PyCharm 更適合做完整的 Python 項目。然而,因為互動式操作,很少會有開發者想到用 Jupyter 做 Debug。 儘管很多 ...
  • 大家好,我是位元組跳動的一名研發麵試官。 2020春招過了,面試也進行了很多場,在整個面試過程中,我不斷被同學問到各式花樣問題: “什麼才是研發麵試考察的核心?” “考前究竟要不要刷題?” “如果跨專業面試要怎麼辦?” “如何更好地描述項目經歷?” “面試中有哪些面試雷區?” ...... 眼看新的一 ...
  • 項目簡介 項目來源於: "https://gitee.com/wu_yun_long/student_management_system" 本系統是基於 Maven+JSP+SSM+Mysql+C3P0 實現的學生管理系統。功能簡單,對業務方面要求低,可以作為學習SSM的入門項目。 難度等級:中等 ...
  • 前言 文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 這篇文章中向大家介紹了Python繪製詞雲的方法,不難看出繪製詞雲可以說是一個“吃瓜神器”,它可以讓我們直觀的看到新聞的核心內容。那麼對於今天的大新聞,我們就繼續用Python ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...