Heim >Datenbank >Redis >Analysieren Sie die Verwendung von Bitmaps in Redis (Erklärung von Beispielszenarien)

Analysieren Sie die Verwendung von Bitmaps in Redis (Erklärung von Beispielszenarien)

藏色散人
藏色散人nach vorne
2021-07-17 16:02:472413Durchsuche

In Redis verwenden wir häufig set, get und andere Befehle. Wenn Sie vorsichtig sind, ist Ihnen aufgefallen, dass es mehrere ähnliche Befehle gibt, die setbit und getbit heißen. ?

Was ist BitMap?

stellt den Wert oder Status dar, der einem bestimmten Element durch ein Bit entspricht, und der Schlüssel ist das entsprechende Element selbst. Wir wissen, dass 8 Bits ein Byte bilden können, sodass die Bitmap selbst erheblich Speicherplatz spart.

BitMap in Redis

Redis hat ab Version 2.2.0 mehrere Bitmap-bezogene Befehle wie setbit, getbit, bitcount usw. hinzugefügt. Obwohl es sich um einen neuen Befehl handelt, werden keine neuen Datentypen hinzugefügt, da Befehle wie setbit lediglich Erweiterungen von set sind.

Einführung in den Befehl „setbit“

Befehl SETBIT Schlüsseloffsetwert
Komplexität O(1)
Setzt oder löscht den Bitwert (nur 0 oder 1) des Schlüsselwerts (String) am Offset.

Speicherplatzbelegung und die für die erste Speicherplatzzuweisung erforderliche Zeit

Auf einem 2010 MacBook Pro beträgt der Offset 2^32-1 (512 MB zugewiesen) und es dauert ~300 ms, und der Offset beträgt 2^30-1 (128 MB zugewiesen) dauert ca. 80 ms, der Offset beträgt 2 ^ 28-1 (32 MB zugewiesen) dauert ca. 30 ms, der Offset beträgt 2 ^ 26-1 (8 MB zugewiesen) dauert 8 ms. hier) Datenimplementierung ist wichtig) und muss den Check-in-Status im letzten Monat anzeigen. Wie sollten wir dies tun, wenn Bitmap verwendet wird? Der Code wird in einem Wort offenbart!

<?php
$redis = new Redis();
$redis->connect('127.0.0.1');

//用户uid
$uid = 1;

//记录有uid的key
$cacheKey = sprintf("sign_%d", $uid);

//开始有签到功能的日期
$startDate = '2017-01-01';

//今天的日期
$todayDate = '2017-01-21';

//计算offset
$startTime = strtotime($startDate);
$todayTime = strtotime($todayDate);
$offset = floor(($todayTime - $startTime) / 86400);

echo "今天是第{$offset}天" . PHP_EOL;

//签到
//一年一个用户会占用多少空间呢?大约365/8=45.625个字节,好小,有木有被惊呆?
$redis->setBit($cacheKey, $offset, 1);

//查询签到情况
$bitStatus = $redis->getBit($cacheKey, $offset);
echo 1 == $bitStatus ? '今天已经签到啦' : '还没有签到呢';
echo PHP_EOL;

//计算总签到次数
echo $redis->bitCount($cacheKey) . PHP_EOL;

/**
* 计算某段时间内的签到次数
* 很不幸啊,bitCount虽然提供了start和end参数,但是这个说的是字符串的位置,而不是对应"位"的位置
* 幸运的是我们可以通过get命令将value取出来,自己解析。并且这个value不会太大,上面计算过一年一个用户只需要45个字节
* 给我们的网站定一个小目标,运行30年,那么一共需要1.31KB(就问你屌不屌?)
*/
//这是个错误的计算方式
echo $redis->bitCount($cacheKey, 0, 20) . PHP_EOL;

Nutzungsszenario 2: Aktive Benutzer zählen

Zeit als Cache-Schlüssel verwenden, und dann wird die Benutzer-ID versetzt, wenn sie an diesem Tag aktiv ist.

Wie soll ich also aktive Benutzer an bestimmten Tagen/Monaten berechnen? Jahre? (Vorerst wird vereinbart, dass nur ein Tag online innerhalb des statistischen Zeitraums als aktiv bezeichnet wird.) Bitte geben Sie den nächsten Redis-Befehl ein: Der Schlüssel zum Speichern binärer Bits führt Bitoperationen aus und speichert das Ergebnis im Zielschlüssel.

Hinweis: Der BITOP-Befehl unterstützt alle Parameter der vier Operationen AND, OR, NOT und

Verwendungsszenario drei: Online-Status des Benutzers

Ich habe vor einiger Zeit ein Projekt entwickelt und die andere Partei hat mir eine Schnittstelle dazu zur Verfügung gestellt Abfrage, ob der aktuelle Benutzer online ist. Ich weiß nicht, wie die andere Partei es macht, also habe ich selbst darüber nachgedacht, dass die Verwendung von Bitmap eine platzsparende und effiziente Methode ist. Es ist nur ein Schlüssel erforderlich, und wenn es online ist, wird es verschoben ist auf 1 gesetzt, und wenn es nicht online ist, wird es auf 1,0 gesetzt. Wie im obigen Szenario benötigt ein 5000-W-Benutzer nur 6 MB Speicherplatz.

//日期对应的活跃用户
$data = array(
'2017-01-10' => array(1,2,3,4,5,6,7,8,9,10),
'2017-01-11' => array(1,2,3,4,5,6,7,8),
'2017-01-12' => array(1,2,3,4,5,6),
'2017-01-13' => array(1,2,3,4),
'2017-01-14' => array(1,2)
);

//批量设置活跃状态
foreach($data as $date=>$uids) {
  $cacheKey = sprintf("stat_%s", $date);
  foreach($uids as $uid) {
    $redis->setBit($cacheKey, $uid, 1);
  }
}

$redis->bitOp('AND', 'stat', 'stat_2017-01-10', 'stat_2017-01-11', 'stat_2017-01-12') . PHP_EOL;
//总活跃用户:6
echo "总活跃用户:" . $redis->bitCount('stat') . PHP_EOL;

$redis->bitOp('AND', 'stat1', 'stat_2017-01-10', 'stat_2017-01-11', 'stat_2017-01-14') . PHP_EOL;
//总活跃用户:2
echo "总活跃用户:" . $redis->bitCount('stat1') . PHP_EOL;

$redis->bitOp('AND', 'stat2', 'stat_2017-01-10', 'stat_2017-01-11') . PHP_EOL;
//总活跃用户:8
echo "总活跃用户:" . $redis->bitCount('stat2') . PHP_EOL;

Empfohlenes Lernen: „
Redis-Video-Tutorial

Das obige ist der detaillierte Inhalt vonAnalysieren Sie die Verwendung von Bitmaps in Redis (Erklärung von Beispielszenarien). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen