Maison  >  Article  >  développement back-end  >  Pratique PHP+REDIS : analyse de plusieurs solutions de comptage de personnes en ligne

Pratique PHP+REDIS : analyse de plusieurs solutions de comptage de personnes en ligne

藏色散人
藏色散人avant
2021-03-17 17:24:263696parcourir

Le comptage des personnes en ligne est la logique métier que nous devons concevoir lors du développement Web. Cet article donnera plusieurs solutions de conception pour analyser les avantages et les inconvénients de chaque solution :

  • Utilisation commandée. set

Cette solution peut stocker simultanément les utilisateurs en ligne et le temps de connexion des utilisateurs, et peut effectuer de nombreux calculs d'agrégation, mais la mémoire consommée est également très considérable.

  • Utiliser une collection

Cette solution permet de stocker des utilisateurs en ligne et peut également effectuer certains calculs d'agrégation. Par rapport aux collections ordonnées, elle consomme de la mémoire. est plus petit, mais à mesure que le nombre d'utilisateurs augmente, la consommation d'espace mémoire augmente également

  • Utiliser hyperloglog

Cette solution Peu importe le nombre les utilisateurs en ligne sont comptés, la mémoire consommée est de 12 Ko, mais seules les informations statistiques des utilisateurs en ligne peuvent être fournies et la liste précise des utilisateurs en ligne ne peut pas être obtenue

  • Utiliser le bitmap

Cette solution est meilleure. Elle enregistre le statut des utilisateurs en ligne tout en économisant autant que possible de l'espace mémoire, et peut effectuer certaines opérations d'agrégation

Utilisons des exemples pratiques ci-dessous Description :

                                                                                                >

Option 1 : Utiliser un ensemble ordonné

pour générer les données d'enregistrement en ligne de l'utilisateur :

$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);
    }
}
D'accord, écrivez-le et voyons quelles informations nous pouvons compter

//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)));

Non seulement ceux-ci, nous pouvons également compter le statut en ligne des utilisateurs le matin, midi, après-midi, soir et à d'autres moments, et il y en a bien d'autres. Utilisons notre imagination. il n'y en a pas beaucoup ? C'est juste que cela consomme beaucoup d'espace mémoire

[Recommandé :

Tutoriel vidéo PHP

]

Option 2 : Utiliser les collections

Tout de même, enregistrons les données en ligne en tant qu'utilisateur :

//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);
    }
}
D'accord, écrivons-les et voyons quelles informations nous pouvons obtenir

//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");

N'est-ce pas plutôt bien Don ? Ne vous inquiétez pas encore. Passons à l'

Option 3 : Utiliser hyperloglgo

Commençons par les utilisateurs à enregistrer des données en ligne :

// 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]);
    }
}
Prenons un regardez cette solution Voyons quels services peuvent être obtenus

$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;));

Il y en a si peu Oui, cette solution ne peut compter que le nombre total de personnes en ligne sur une certaine période de temps, mais elle ne peut rien faire. sur la liste des utilisateurs en ligne, mais c'est plutôt bien. On peut envisager cette solution si elle économise de la mémoire et ne nécessite pas beaucoup de données statistiques.

Option 4 : Utiliser le bitmap

L'auteur aime en fait cette solution. Elle ne consomme pas beaucoup d'espace mémoire mais contient beaucoup d'informations statistiques. , générez d'abord des données :

//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);
    }
}
Ensuite, jetons un coup d'œil aux informations statistiques qui le satisfont. Que diriez-vous de

//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;));

 ? Si la collection peut être comptée, ce type peut-il aussi la compter ? Et cela consomme moins de contenu.

En fait, chacune de ces solutions a ses propres avantages Selon les statistiques de l'entreprise, choisissez la solution correspondante à mettre en œuvre, afin que l'utilisation de la mémoire soit plus raisonnable

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer