Redis ビットマップを使用してアクティブ ユーザーをカウントする

齐天大圣
リリース: 2020-05-20 09:01:17
オリジナル
2207 人が閲覧しました

まず、シナリオを見てみましょう。Web サイトでは、1 週間以内に継続的にログインしたユーザーと、1 か月以内にログインしたユーザーをカウントする必要があります。

Mysql などの従来のデータベースを使用して実装した場合、実現は困難です。しかし、Redis を使用すると、それは非常に簡単になります。 Redisのコレクション型とビットマップ型を簡単に実現できます。今日は主に、ビットマップを使用してアクティブユーザーをカウントする機能を実装する方法について説明します。

ビットマップ

コンピューター システムでは、情報の最小単位はバイトです。1 バイトは 8 ビットに相当します。各ビットは、 0 または 1 のみを指定できます (コンピュータはこれら 2 つの数値のみを認識します)。ビットマップを使用すると、ビットを直接操作できます。

ビッグマップは配列と見なされます。配列内の各ビットは 0 または 1 のみです。ここでは配列の添え字がオフセットとみなされます。

ビットマップに関連するいくつかのコマンドを紹介します。

setbit

#setbit キー オフセット値:対応するビットの値を設定します。

たとえば、ユーザー 3、8、23、および 32 が今日 Web サイトにアクセスした場合、

setbit user:view:2020-5-17 3 1
setbit user:view:2020-5-17 8 1
setbit user:view:2020-5-17 23 1
setbit user:view:2020-5-17 32 1
ログイン後にコピー

開発のヒント: 多くのアプリケーション ID は 1 から始まりませんが、多くは 1001、10001 などの指定された番号から始まります。これらについては、スペースの無駄を防ぐために、設定時に初期値を減算することができます。

getbit

#getbit キー オフセットは、指定したビットの値

ユーザー No. 8 とユーザー No. 45 が今日ログインしているかどうかを知りたい場合は、

127.0.0.1:6379> getbit user:view:2020-5-17 8
(integer) 1
127.0.0.1:6379> getbit user:view:2020-5-17 45
(integer) 0
ログイン後にコピー

ユーザー No. 8 が表示されます。は今日ログインしましたが、ユーザー番号 45 は今日ログインしていません。

#bitcount

bitcount key [start] [end] 指定範囲 1

## の数値を取得します

#今日ログインしたユーザーの数を知りたいので、

127.0.0.1:6379> bitcount user:view:2020-5-17
(integer) 4
ログイン後にコピー

ビットマップ間の操作

bitop op destkey key [key ...]

bitop コマンドは、複数のビットマップに対して論理積 (and)、結合 (or)、非 (not)、排他的論理和 (xor) を実行でき、演算結果を返します。 destkeyに保存されます。 3日連続でログインしたユーザー数、つまり5月17日、18日、19日にログインしたユーザー数を知りたい場合。

過去 3 日間のログイン状況は次のとおりです。

5 月 17 日、3 日、8 日、23 日、32 人のユーザーがログインしました

  • ユーザー No. 3、23、43、および 54 は 5 月 18 日にログインしました

  • ユーザー No.3、5、23、32、56、および 78 5 月 19 日にログインしました

  • 127.0.0.1:6379> bitop and three:and user:view:2020-5-17 user:view:2020-5-18 user:view:2020-5-19
    127.0.0.1:6379> bitcount three:and
    (integer) 2
    ログイン後にコピー

    過去 3 日間にログインしたユーザーの数を知りたい場合。

    127.0.0.1:6379> bitop or three:or user:view:2020-5-17 user:view:2020-5-18 user:view:2020-5-19
    (integer) 10
    127.0.0.1:6379> bitcount three:or
    (integer) 9
    ログイン後にコピー
  • ご覧のとおり、過去 3 日間に合計 9 人のユーザーがログインしました。

実践的な戦闘

上記の知識を完了したら、必要な要件を完了できます。つまり、一定期間内の連続ログイン数をカウントする必要があります。週単位のユーザー、および 1 か月以内にログインしたユーザー。 まず、30 日以内のユーザーのログイン状況をシミュレートします。疑似コードは次のとおりです:

for ($i = 0; $i < 20000; $i++) {
    $userId = mt_rand(1, 10000);
    $date   = time() - 86400 * mt_rand(0, 30);
    $key   = &#39;userlogin_&#39;.date(&#39;Ymd&#39;, $date);
 
    $redis->setBit($key, $userId, 1);
}
ログイン後にコピー

1 週間以内にログインしたユーザーを取得します。もちろん、すべてを取得するわけではありません。ある数値だけをまとめて取得したいのですが、ページングのように一度に取得したいので、ある程度の数の疑似コードは次のとおりです:

for ($i = 1; $i <= 7; $i ++) {
    $key = "userlogin_".date(&#39;Ymd&#39;, time() - (86400*$i));
 
    if ($i == 1) {
        $redis->bitOp(&#39;and&#39;, &#39;week_logined&#39;, $key);
    } else {
        $redis->bitOp(&#39;and&#39;, &#39;week_logined&#39;, &#39;week_logined&#39;, $key);
    }
}
 
// 获取前50个用户
$userIds = [];
for ($i=1; $i<=10000; $i++) {
    $ret = $redis->getBit(&#39;week_logined&#39;, $i);
    $ret && $userIds[] = $i;
 
    if (count($userIds) >=50) break;
}
ログイン後にコピー

注意点があり、エラーでもあります。初回のビトップ時は、week_logined がまだ存在しないため、操作が実行されます。キーは 1 つだけです。 2回目から始める場合はopのキーが2つあります。

1 か月以内にログインしたユーザーを取得する場合、考え方は基本的に上記と同じですが、and が or

for ($i = 1; $i <= 3; $i ++) {
    $key = "userlogin_".date(&#39;Ymd&#39;, time() - (86400*$i));
    $redis->bitOp(&#39;or&#39;, &#39;month_loginOnce&#39;, &#39;month_loginOnce&#39;, $key);
}
 
// 获取一个月内登陆过的用户
$userIds = [];
for ($i=1; $i<=10000; $i++) {
    $ret = $redis->getBit(&#39;month_loginOnce&#39;, $i);
    $ret && $userIds[] = $i;
}
ログイン後にコピー
に変更される点が異なります。ご覧のとおり、 doing or と and.of にはまだいくつかの違いがあります。または、最初から判断する必要はありません。理由は誰でも理解できるからです。

以上がRedis ビットマップを使用してアクティブ ユーザーをカウントするの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート