ホームページ  >  記事  >  バックエンド開発  >  Redis はユーザーのチェックインを実装し、アクティブ ユーザーをカウントし、ユーザーのオンライン ステータスをカウントします。

Redis はユーザーのチェックインを実装し、アクティブ ユーザーをカウントし、ユーザーのオンライン ステータスをカウントします。

假装我是个程序员
假装我是个程序员オリジナル
2018-05-19 15:07:506378ブラウズ

開発プロセス中に、ユーザーのチェックイン、その日のアクティブユーザーの統計、各ユーザーのオンラインステータスなどの開発ニーズが発生する場合があります。対応するニーズに応じて、従来の方法を使用してデータベーステーブルを設計する場合があります。これは多くのストレージ容量を消費し、パフォーマンスもあまり良くありません。以下はシンプルで使いやすい方法です。

実装方法を紹介する前に、まずRedisのキーワード「ビットマップ」についてご紹介します

ビットマップとは

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

Redis の BitMap

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

setbitコマンド紹介

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

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

2010 MacBook Pro では、オフセット 2^32-1 (512MB 割り当て) の場合は ~300ms、オフセット 2^30 の場合は ~300ms かかります。 -1 (128MB 割り当て) ~ 80 ミリ秒、オフセットが 2^28-1 (32MB 割り当て) の場合は ~ 30 ミリ秒、オフセットが 2^26-1 (8MB 割り当て) の場合は 8 ミリ秒かかります。
おおよそのスペース占有計算式は次のとおりです: ($offset/8/1024/1024)MB

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

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

<?php
$redis = new Redis();
$redis->connect(&#39;127.0.0.1&#39;);


//用户uid
$uid = 1;

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

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

//今天的日期
$todayDate = &#39;2017-01-21&#39;;

//计算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 ? &#39;今天已经签到啦&#39; : &#39;还没有签到呢&#39;;
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 コマンドを実行してください
コマンド BITOP 操作 destkey key [key...]
説明: 格納されている 1 つ以上の文字列キーを実行します。 binary bits ビット演算を行い、結果を destkey に保存します。
注: BITOP コマンドは、AND、OR、NOT、XOR の 4 つの演算の任意のパラメーターをサポートします

//日期对应的活跃用户

$data = array(

&#39;2017-01-10&#39; => array(1,2,3,4,5,6,7,8,9,10),

&#39;2017-01-11&#39; => array(1,2,3,4,5,6,7,8),

&#39;2017-01-12&#39; => array(1,2,3,4,5,6),

&#39;2017-01-13&#39; => array(1,2,3,4),

&#39;2017-01-14&#39; => array(1,2)

);



//批量设置活跃状态

foreach($data as $date=>$uids) {

$cacheKey = sprintf("stat_%s", $date);

foreach($uids as $uid) {

$redis->setBit($cacheKey, $uid, 1);

}

}



$redis->bitOp(&#39;AND&#39;, &#39;stat&#39;, &#39;stat_2017-01-10&#39;, &#39;stat_2017-01-11&#39;, &#39;stat_2017-01-12&#39;) . PHP_EOL;

//总活跃用户:6

echo "总活跃用户:" . $redis->bitCount(&#39;stat&#39;) . PHP_EOL;



$redis->bitOp(&#39;AND&#39;, &#39;stat1&#39;, &#39;stat_2017-01-10&#39;, &#39;stat_2017-01-11&#39;, &#39;stat_2017-01-14&#39;) . PHP_EOL;

//总活跃用户:2

echo "总活跃用户:" . $redis->bitCount(&#39;stat1&#39;) . PHP_EOL;



$redis->bitOp(&#39;AND&#39;, &#39;stat2&#39;, &#39;stat_2017-01-10&#39;, &#39;stat_2017-01-11&#39;) . PHP_EOL;

//总活跃用户:8

echo "总活跃用户:" . $redis->bitCount(&#39;stat2&#39;) . PHP_EOL;

使用场景三:用户在线状态

前段时间开发一个项目,对方给我提供了一个查询当前用户是否在线的接口。不了解对方是怎么做的,自己考虑了一下,使用bitmap是一个节约空间效率又高的一种方法,只需要一个key,然后用户ID为offset,如果在线就设置为1,不在线就设置为0,和上面的场景一样,5000W用户只需要6MB的空间。

//批量设置在线状态
$uids = range(1, 500000);

foreach($uids as $uid) {

$redis->setBit(&#39;online&#39;, $uid, $uid % 2);

}

//一个一个获取状态

$uids = range(1, 500000);

$startTime = microtime(true);

foreach($uids as $uid) {

echo $redis->getBit(&#39;online&#39;, $uid) . PHP_EOL;

}

$endTime = microtime(true);

//在我的电脑上,获取50W个用户的状态需要25秒

echo "total:" . ($endTime - $startTime) . "s";




/**

* 对于批量的获取,上面是一种效率低的办法,实际可以通过get获取到value,然后自己计算

* 具体计算方法改天再写吧,之前写的代码找不见了。。。

*/

其实BitMap可以运用的场景很多很多(当然也会受到一些限制),思维可以继续扩散~欢迎小伙伴给我留言探讨~

以上がRedis はユーザーのチェックインを実装し、アクティブ ユーザーをカウントし、ユーザーのオンライン ステータスをカウントします。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。