ホームページ  >  記事  >  バックエンド開発  >  PHP+REDIS の実践: オンライン人数をカウントするためのいくつかのソリューションの分析

PHP+REDIS の実践: オンライン人数をカウントするためのいくつかのソリューションの分析

藏色散人
藏色散人転載
2021-03-17 17:24:263787ブラウズ

オンライン人数カウント ビジネスは、Web 開発時に設計する必要があるビジネス ロジックです。この記事では、各ソリューションの長所と短所を分析するためにいくつかの設計ソリューションを示します:

  • Use Ordered set

このソリューションは、オンライン ユーザーとユーザーのオンライン時間を同時に保存し、多くの集計計算を実行できますが、消費されるメモリも非常に多くなります。

  • セットを使用する

このソリューションでは、オンライン ユーザーを保存でき、特定の集計計算も実行できます。順序付きセットと比較して、メモリの消費量が少なくなります。は小さくなりますが、ユーザー数が増加するにつれて、消費されるメモリ領域も増加します

  • ハイパーログログを使用します

このソリューションはユーザー数に関係なく、オンライン ユーザーはカウントされ、消費されるメモリは 12k ですが、提供できるのはオンライン ユーザーの統計情報のみであり、オンライン ユーザーの正確なリストは取得できません

  • ビットマップを使用してください

このソリューションはまだ比較的優れています。メモリ領域を可能な限り節約しながらオンライン ユーザーのステータスを記録し、特定の集計操作を実行できます。

以下の実践的な例を使用してみましょう注:

# 说 まず、毎日 10 ~ 30 W の少数のユーザーがおり、100 W のユーザー グループは次のスキームを示します

# #Q :順序付きセットを使用します

最初にユーザーのオンライン記録データを生成します:

$start_time = mktime(0, 0, 0, 9, 5);    //monday
for ($i=0; $i < 6; $i++) {
    $day_start_time  = $start_time + 86400 * $i;    //every day begin time
    $day_end_time =  $day_start_time + 86400;       //every day end time
    $online_user_num = mt_rand(100000, 300000);     //online user between 100000 and 300000 
    for ($j=1; $j < $online_user_num; $j++) { 
        $user_id = mt_rand(1, 1000000);
        $redis->zadd(&#39;000|online_users_day_&#39;.$i, mt_rand($day_start_time, $day_end_time), $user_id);
    }
}

わかりました、書き留めて、どのような情報がカウントできるか見てみましょう

//note: 统计每天的在线总人数
for ($i=0; $i < 6; $i++) { 
    print_r($redis->zsize(&#39;000|online_users_day_&#39;.$i). "\n");
}
//note: 统计最近6天都在线的人数
var_dump($redis->zInter(&#39;000|online_users_day_both_6&#39;, 
    [
    &#39;000|online_users_day_0&#39;, 
    &#39;000|online_users_day_1&#39;, 
    &#39;000|online_users_day_2&#39;, 
    &#39;000|online_users_day_3&#39;, 
    &#39;000|online_users_day_4&#39;, 
    &#39;000|online_users_day_5&#39;
    ]
    ));
//note: 统计出近6天中共有多少上线
$redis->zunion(&#39;000|online_users_day_total_6&#39;, [&#39;000|online_users_day_0&#39;, &#39;000|online_users_day_1&#39;, &#39;000|online_users_day_2&#39;, &#39;000|online_users_day_3&#39;, &#39;000|online_users_day_4&#39;, &#39;000|online_users_day_5&#39;]);
//note: 统计某个时间段总共在线用户
print_r($redis->zcount(&#39;000|online_users_day_5&#39;, mktime(13, 0, 0, 9, 10), mktime(14, 0, 0, 9, 10)));
//note: 统计某个时间段在线用户名单
print_r($redis->zrangebyscore(&#39;000|online_users_day_5&#39;, mktime(13, 0, 0, 9, 10), mktime(14, 0, 0, 9, 10), 
    array(&#39;withscores&#39; => TRUE)));

これだけでなく、朝、昼、昼、夕方などの時間帯ごとのユーザーのオンライン状況をカウントしたり、想像力を働かせてみましょう。ただ、大量のメモリ空間を消費します。

[推奨:

PHP ビデオ チュートリアル]

オプション 2: コレクションを使用する

または まず、ユーザーのためにオンラインでデータを記録しましょう:

//note set 一般聚合
for ($i=0; $i < 6; $i++) {
    $online_user_num = mt_rand(100000, 300000);     //online user between 100000 and 300000 
    for ($j=1; $j < $online_user_num; $j++) { 
        $user_id = mt_rand(1, 1000000);
        $redis->sadd(&#39;001|online_users_day_&#39;.$i, $user_id);
    }
}

わかりました、書き留めて、どのような情報が得られるか見てみましょう。

//note 判断某个用户是否在线
var_dump($redis->sIsMember(&#39;001|online_users_day_5&#39;, 100030));
//note 每天在线用户总量的统计
for ($i=0; $i < 6; $i++) { 
    print_r($redis->ssize(&#39;001|online_users_day_&#39;.$i). "\n");
}
//note 对不同时间段的在线用户名单进行聚合
print_r($redis->sInterStore(&#39;001|online_users_day_both_4and5&#39;, &#39;001|online_users_day_4&#39;, &#39;001|online_users_day_5&#39;). "\n");
//note 对指定的时间段的在线用户名单进行统计
print_r($redis->sUnionStore(&#39;001|online_users_day_total_4add5&#39;, &#39;001|online_users_day_4&#39;, &#39;001|online_users_day_5&#39;). "\n");
//note 哪天上线哪天没上线
print_r($redis->sDiffStore(&#39;001|online_users_day_diff_4jian5&#39;, &#39;001|online_users_day_4&#39;, &#39;001|online_users_day_5&#39;). "\n");

なかなか良いものではないですか? やめてください。

オプション 3: hyperloglgo を使用する

まずユーザーのところに来て、オンラインでデータを記録します:

// note HyperLogLog 只需要知道在线总人数
for ($i=0; $i < 6; $i++) {
    $online_user_num = mt_rand(100000, 300000);     //online user between 100000 and 300000 
    var_dump($online_user_num);
    for ($j=1; $j < $online_user_num; $j++) { 
        $user_id = mt_rand(1, 1000000);
        $redis->pfadd(&#39;002|online_users_day_&#39;.$i, [$user_id]);
    }
}

では、次のことを考えてみましょう。このソリューションを見てみましょう。どのようなサービスが実現できるか見てみましょう。

$count = 0;
for ($i=0; $i < 3; $i++) { 
    $count += $redis->pfcount(&#39;002|online_users_day_&#39;.$i);
    print_r($redis->pfcount(&#39;002|online_users_day_&#39;.$i). "\n");
}
var_dump($count);
//note  3 days total online num
var_dump($redis->pfmerge(&#39;002|online_users_day_both_3&#39;, [&#39;002|online_users_day_0&#39;, &#39;002|online_users_day_1&#39;, &#39;002|online_users_day_2&#39;]));
var_dump($redis->pfcount(&#39;002|online_users_day_both_3&#39;));

数は非常に少ないです。はい、このソリューションでは、一定期間内のオンラインユーザーの総数をカウントすることしかできませんが、カウントすることはできません。オンライン ユーザーのリストについては何でもできますが、これは非常に優れており、メモリを節約し、統計データをあまり必要としない場合は、このソリューションを検討できます。

オプション 4: ビットマップを使用する

作者は実際にこのソリューションを気に入っています。多くのメモリ領域を消費しませんが、大量の統計情報が含まれています。まだ古いものです。手順、まずデータを生成します:

//note bitmap 综合前面3个的优缺点
for ($i=0; $i < 6; $i++) {
    $online_user_num = mt_rand(100000, 300000);     //online user between 100000 and 300000 
    for ($j=1; $j < $online_user_num; $j++) { 
        $user_id = mt_rand(1, 1000000);
        $redis->setbit(&#39;003|online_users_day_&#39;.$i, $user_id, 1);
    }
}

次に、

//note userid today whether online 
var_dump($userid = mt_rand(1, 1000000));
var_dump($redis->getbit(&#39;003|online_users_day_5&#39;, $userid));
//note how many user is online
var_dump($redis->bitcount(&#39;003|online_users_day_5&#39;));
//note 6 days both online
var_dump($redis->bitop(&#39;AND&#39;, &#39;003|online_users_day_both_6&#39;, &#39;003|online_users_day_0&#39;, &#39;003|online_users_day_1&#39;, &#39;003|online_users_day_2&#39;, &#39;003|online_users_day_3&#39;, &#39;003|online_users_day_4&#39;, &#39;003|online_users_day_5&#39;));
var_dump($redis->bitcount(&#39;003|online_users_day_both_6&#39;));
//note 6 days total online
var_dump($redis->bitop(&#39;OR&#39;, &#39;003|online_users_day_total_6&#39;, &#39;003|online_users_day_0&#39;, &#39;003|online_users_day_1&#39;, &#39;003|online_users_day_2&#39;, &#39;003|online_users_day_3&#39;, &#39;003|online_users_day_4&#39;, &#39;003|online_users_day_5&#39;));
var_dump($redis->bitcount(&#39;003|online_users_day_total_6&#39;));
//note 6 days only one online
var_dump($redis->bitop(&#39;XOR&#39;, &#39;003|online_users_day_only_one_6&#39;, &#39;003|online_users_day_0&#39;, &#39;003|online_users_day_1&#39;, &#39;003|online_users_day_2&#39;, &#39;003|online_users_day_3&#39;, &#39;003|online_users_day_4&#39;, &#39;003|online_users_day_5&#39;));
var_dump($redis->bitcount(&#39;003|online_users_day_only_one_6&#39;));

を満たすことができる統計情報を見てみましょう。コレクションが数えられるなら、この男も数えられるでしょうか?そして消費するコンテンツも少なくなります。

実際には、これらのソリューションにはそれぞれ独自の利点があります。ビジネス統計に従って、メモリ使用率がより適切になるように、対応するソリューションを選択して実装してください。

以上がPHP+REDIS の実践: オンライン人数をカウントするためのいくつかのソリューションの分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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