ホームページ  >  記事  >  データベース  >  Redisにおけるビットマップの利用状況を分析する(サンプルシナリオの説明)

Redisにおけるビットマップの利用状況を分析する(サンプルシナリオの説明)

藏色散人
藏色散人転載
2021-07-17 16:02:472375ブラウズ

Redis では、set、get、およびその他のコマンドがよく使用されます。注意していれば、類似したコマンドがいくつかあることに気づきましたか?コマンドは setbit と getbit と呼ばれますが、何に使用されますか?

BitMap とは

# ビットを使用して要素に対応する値またはステータスを表し、キーは対応する要素そのものです。 8 ビットでバイトを形成できることがわかっているため、ビットマップ自体によりストレージ スペースが大幅に節約されます。

Redis のビットマップ

Redis は、バージョン 2.2.0 以降、setbit、getbit、bitcount などのビットマップ関連のコマンドをいくつか追加しました。これは新しいコマンドですが、setbit などのコマンドは set の単なる拡張であるため、新しいデータ型は追加されません。

setbit コマンドの紹介

コマンド SETBIT キー オフセット値

Complexity O(1)
オフセットのキーの値 (文字列) を設定またはクリアしますのビット値 (0 または 1 のみ)。

スペース占有と、初めてスペースを割り当てるのに必要な時間

2010 MacBook Pro では、オフセットは 2^32-1 (512MB 割り当て) ~ 300ms、オフセットが 2^30-1 (128MB 割り当て) の場合は ~80ms、オフセットが 2^28-1 (32MB 割り当て) の場合は ~30ms、オフセットが 2^26-1 (8MB 割り当て) の場合は 8ms かかります。

おおよそのスペース占有計算式は次のとおりです: ($offset/8/1024/1024)MB

使用シナリオ 1: ユーザー サインイン

多くの Web サイトではチェックイン機能が提供されており (ここではデータの実装は考慮されていません)、過去 1 か月のチェックイン状況を表示する必要があります。ビットマップを使用するにはどうすればよいでしょうか?暗号は一言で判明!

<?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;

使用シナリオ 2: アクティブ ユーザーのカウント

時間をキャッシュキーとして使用し、ユーザー ID をオフセットします。その日にアクティブな場合は、次のように設定します。 1

次に、特定の日/月/年のアクティブ ユーザーを計算する方法 (当面は、統計期間中にオンラインになった 1 日だけをアクティブと呼ぶことに同意します) を行うには、次の redis コマンド ## を使用してください。 #Command BITOP 操作 destkey key [key .. .]
説明: バイナリ ビットを格納する 1 つ以上の文字列キーに対してビット操作を実行し、結果を destkey に保存します。
注: BITOP コマンドは、AND、OR、NOT、および /1024=6MB

# 4 つの操作の任意のパラメーターをサポートします。使用シナリオ 3: ユーザーのオンライン ステータス

私は少し前にプロジェクトを開発しましたが、相手は現在のユーザーがオンラインかどうかを問い合わせるためのインターフェースを私に提供してくれました。相手がどうやってるか分からないので自分で考えました ビットマップを使うのが省スペースで効率的な方法です 必要なキーは 1 つだけで、ユーザー ID はオフセットされます オンラインであれば、は 1 に設定され、オンラインでない場合は 1.0 に設定されます。上記のシナリオと同様に、5000W ユーザーには 6MB のスペースのみが必要です。

//日期对应的活跃用户
$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;
推奨学習: 「redis ビデオ チュートリアル

以上がRedisにおけるビットマップの利用状況を分析する(サンプルシナリオの説明)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。