Data sharing of Swoole multiprocess through Swoole\Table

Third party storage media

Previously, we introduced the Process and Process\Pool modules based on Swoole to realize multi Process management in PHP. However, in the multi Process mode, processes are isolated from each other and cannot share data and variables. Even global or super global variables defined through global are only valid in their own processes. If they are to be used in Swoole The realization of data sharing among multiple processes requires the use of third-party storage media:

  • Database: MySQL, MongoDB
  • Cache: Redis, Memcached
  • Disk file

But this will also lead to new problems. There is A concurrent access problem when multiple processes operate A record or A file at the same time. Take database operation as an example, two processes may read A data at the same time, or when one process updates A record, the other process will read the record and operate, which will lead to the inconsistency between the final result data and the expected data In this case, we need to introduce the concept of lock. When A process (such as process A) writes A record, lock the record, so that other processes cannot operate the record until process A commits the transaction and releases the lock, so that other processes can operate.

Memory sharing

PHP related extensions

For stand-alone operations, in addition to these third-party storage media, inter process data read and write operations can be realized by sharing memory. There are multiple PHP extensions that can support shared memory data operations:

  • Semaphore extension : the functions of SHM get VaR and SHM put var provided by the extension package can be used to read and write memory shared data;
  • Shmop extension : the shmop read and shmop write functions provided by the extension package can be used to read and write memory shared data;
  • APCu (APC User Cache) extension : read and write operation of memory shared data can be realized through APC fetch and APC store provided by the extension package.

Swoole Table

However, the above extensions either do not support locks or perform poorly in high concurrency, so Swoole has implemented a shared memory read-write tool of its own, Swoole\Table. This tool is a high-performance concurrent data structure based on shared memory and locks, which can be used to solve the problems of multi process / multi thread data sharing and synchronous locking:

  • Powerful performance, single thread can read and write 2 million times per second;
  • The application code does not need to be locked, and the row lock is built-in. All operations are multithreaded / multiprocess safe. The user layer does not need to consider the data synchronization problem at all;
  • It supports multiple processes and can be used to share data among multiple processes;
  • Row lock is used instead of global lock. Only when two processes are in the same CPU time, they can read the same data simultaneously to rob lock.

Swoole\Table supports key value reading and writing, which is very simple to use:

<?php

// Initialize a Swoole Table with a capacity of 1024
$table = new \Swoole\Table(1024);
// Add id column in Table
$table->column('id', \Swoole\Table::TYPE_INT);
// Add a name column in the Table with a length of 50
$table->column('name', \Swoole\Table::TYPE_STRING, 10);
// New score column in Table
$table->column('score', \Swoole\Table::TYPE_FLOAT);
// Create this Swoole Table
$table->create();


// Set key value value
$table->set('student-1', ['id' => 1, 'name' => 'Learn from Xiaojun', 'score' => 80]);
$table->set('student-2', ['id' => 2, 'name' => 'Academician', 'score' => 90]);

// Print the corresponding Value if the specified Key Value exists
if ($table->exist('student-1')) {
    echo "Student-" . $table->get('student-1', 'id') . ':' . $table->get('student-1', 'name').":".
        $table->get('student-1', 'score') . "\n";
}

// Auto increment operation
$table->incr('student-2', 'score', 5);
// Self reducing operation
$table->decr('student-2', 'score', 5);

// Total records in the table
$count = $table->count();

// Delete specified table record
$table->del('student-1');

  

In addition, the Swoole\Table class implements the iterator interface and supports traversal through foreach.

Use Swoole\Table in Laravel

If you want to integrate Swoole in Laravel, use Swoole\Table to LaravelS expansion pack For example, first define the swoole table configuration item in the configuration file config/laravels.php:

'swoole_tables'            => [
    'ws' => [ // The Table name will be suffixed with the Table suffix. For example, here is wsTable
        'size'   => 102400, //  Table capacity
        'column' => [ // Table field named value
            ['name' => 'value', 'type' => \Swoole\Table::TYPE_INT, 'size' => 8],
        ],
    ],
    ... // Other tables can also be defined
],

  

Then we can access the SwooleTable through the wsTable property on the swoole instance in the code:

class WebSocketService implements WebSocketHandlerInterface
{
    ...

    // Triggered when a connection is established
    public function onOpen(Server $server, Request $request)
    {
        // Before triggering the WebSocket connection establishment event, the life cycle of Laravel application initialization is over. You can get Laravel request and session data here
        // Call the push method to push data to the client. fd is the client connection identification field
        Log::info('WebSocket Connection establishment:' . $request->fd);
        app('swoole')->wsTable->set('fd:' . $request->fd, ['value' => $request->fd]);
        $server->push($request->fd, 'Welcome to WebSocket Server built on LaravelS');
    }

    // Triggered when a message is received
    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']);
                // Call the push method to push data to the client
                $server->push($frame->fd, 'This is a message sent from WebSocket Server at ' . date('Y-m-d H:i:s'));
            }
        }
    }
    
    ...

}

  

Then we refer to Integrating Swoole to implement WebSocket server in Laravel In this tutorial, you can see the corresponding log information in the latest log file by sending a request from the client to the WebSocket server:

[2020-04-24 19:39:03] local.INFO: WebSocket Connection establishment:1  
[2020-04-24 19:39:07] local.INFO: Receive message from client: 1

  



Tags: PHP Laravel Database MySQL

Posted on Fri, 24 Apr 2020 05:42:16 -0700 by slewis1959