Signatur
Beschreibung
Swoole\Table implementiert eine auf gemeinsamem Speicher (Shared Memory) basierende Hashtabelle, die von mehreren Worker-Prozessen gleichzeitig gelesen und beschrieben werden kann. Sie eignet sich hervorragend für den prozessübergreifenden Datenaustausch ohne IPC-Overhead (z. B. ohne Unix-Sockets oder Redis), etwa für Sitzungsdaten, Verbindungszähler oder Rate-Limiting-Strukturen.
Im Gegensatz zu PHP-Arrays oder APCu ist Swoole\Table explizit für parallele Zugriffe ausgelegt und bietet eingebaute atomare Operationen (incr, decr). Der Speicher wird einmalig beim Erstellen reserviert und ist auf die bei create() angegebene Zeilenanzahl begrenzt.
Bevor die Tabelle benutzt werden kann, müssen alle Spalten mit column() definiert und anschließend create() aufgerufen werden. Nachträglich lassen sich keine Spalten mehr hinzufügen. Zulässige Spaltentypen sind Swoole\Table::TYPE_INT, Swoole\Table::TYPE_FLOAT und Swoole\Table::TYPE_STRING.
Die Klasse implementiert Iterator und Countable, sodass man über alle Zeilen iterieren und die aktuelle Anzahl belegter Einträge per count() abrufen kann.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $table_size Pflicht | int | Maximale Anzahl von Zeilen der Tabelle. Der tatsächlich reservierte Speicher wird auf die nächste Zweierpotenz aufgerundet. | |
| $conflict_proportion | float | 0.2 | Anteil zusätzlicher Einträge, die für Hash-Kollisionen reserviert werden (0.0–1.0). Der tatsächliche Speicherbedarf erhöht sich entsprechend. |
Beispiele
Verbindungszähler für mehrere Worker
<?php
// Tabelle VOR dem Start des Servers anlegen
$table = new Swoole\Table(1024);
$table->column('connections', Swoole\Table::TYPE_INT);
$table->column('last_ip', Swoole\Table::TYPE_STRING, 46);
$table->create();
$server = new Swoole\WebSocket\Server('0.0.0.0', 9501);
$server->table = $table;
$server->on('open', function (Swoole\WebSocket\Server $server, $request) {
// Atomares Inkrementieren — threadsicher
$server->table->incr('stats', 'connections', 1);
$server->table->set('stats', ['last_ip' => $request->server['remote_addr']]);
echo 'Verbindungen gesamt: ' . $server->table->get('stats', 'connections') . PHP_EOL;
});
$server->on('close', function (Swoole\WebSocket\Server $server, int $fd) {
$server->table->decr('stats', 'connections', 1);
});
$server->on('message', function () {});
// $server->start();
Einfaches Lesen, Schreiben und Iterieren
<?php
$table = new Swoole\Table(512);
$table->column('name', Swoole\Table::TYPE_STRING, 64);
$table->column('score', Swoole\Table::TYPE_INT);
$table->create();
$table->set('user:1', ['name' => 'Alice', 'score' => 100]);
$table->set('user:2', ['name' => 'Bob', 'score' => 200]);
// Einzelwert lesen
echo $table->get('user:1', 'name') . PHP_EOL; // Alice
// Score atomar erhöhen
$table->incr('user:2', 'score', 50);
echo $table->get('user:2', 'score') . PHP_EOL; // 250
// Über alle Einträge iterieren
foreach ($table as $key => $row) {
echo $key . ': ' . $row['name'] . ' => ' . $row['score'] . PHP_EOL;
}
// Zeile löschen
$table->del('user:1');
echo 'Verbleibende Einträge: ' . count($table) . PHP_EOL; // 1
// Wichtig · Fallstricke
Speicher wird fest reserviert: Der bei der Konstruktion angegebene Speicher wird sofort und dauerhaft als Shared Memory belegt. Eine zu groß gewählte Tabelle verschwendet RAM; eine zu klein gewählte führt zu Einfügefehlern, wenn sie voll ist. Plane den Bedarf sorgfältig.
Reihenfolge der Initialisierung: column() und create() müssen zwingend aufgerufen werden, bevor der Swoole-Server gestartet wird (start()). Andernfalls kann die Tabelle nicht zwischen den Worker-Prozessen geteilt werden.
Keine dynamischen Schlüssel: Die Anzahl der Spalten und ihre Typen sind nach create() unveränderlich. Strings werden auf die bei column() angegebene Maximallänge gekürzt.
Atomare Operationen: incr() und decr() sind atomar und für den parallelen Einsatz geeignet. set() hingegen ist es nicht vollständig — für komplexe Lese-Modifiziere-Schreibe-Zyklen sollte ein Swoole\Lock verwendet werden.