LoginSignup
1
1

More than 5 years have passed since last update.

Redisのsrandmemberがおかしい

Last updated at Posted at 2014-12-30

Redisのsrandmemberのバラつきがおかしい

現象

Redisのセット型の関数にsrandmemberがありますが、この関数のバラつき型がおかしい事に気付いたので、備忘録代わりに。

どういう時におかしくなるのか

  • キーが数値の場合には問題が無い。
  • キーが文字列に確率がおかしくなる。
  • キーが文字列でも確率がおかしくならない場合がある。
  • 文字列のときの条件はわからない。(そこまで調べる気もあまりない
  • キーは数値を使った方がいいよ

再現コード

sample.pl
#!/usr/bin/env perl
use 5.16.2;
use strict;
use warnings;
use utf8;

use Redis::Fast;

my $redis = Redis::Fast->new;

my $elements_count = 5;
my $try_count = 1000;
my $result;

$redis->del("test");
$result = {};

say "### 要素数 $elements_count 数値の場合";
say "|キー名|取得数|確率|";
say "| ---- | ---- | ---- |";
$redis->sadd("test" , $_) for 1..$elements_count;
$result->{$redis->srandmember("test")}++ for 1..$try_count;
for(1..$elements_count){
    say "|" . (join " | " , sprintf("%-4s", $_) , sprintf("%-3s" , $result->{$_}) , (100 * $result->{$_} / $try_count) . "%") . "|";
}

$redis->del("test");
$result = {};

say "";
say "### 要素数 $elements_count 文字列の場合";
say "キー名|取得数|確率";
$redis->sadd("test" , "test$_") for 1..$elements_count;
$result->{$redis->srandmember("test")}++ for 1..$try_count;
for(1..$elements_count){
    say "|" . (join " | " , sprintf("%-8s", "test$_") , sprintf("%-3s" , $result->{"test$_"}) , (100 * $result->{"test$_"} / $try_count) . "%") . "|";
}

結果

  • 要素数5個,試行回数は1000回の時、文字列の場合の取得確率が均等になっていない
  • 要素数10個,試行回数は1000回の時、文字列の取得が均等になっている
  • 要素数20個,試行回数10万回の時、均等になっていない

要素数 5 数値の場合

キー名 取得数 確率
1 195 19.5%
2 209 20.9%
3 209 20.9%
4 195 19.5%
5 192 19.2%

要素数 5 文字列の場合

キー名 取得数 確率
test1 125 12.5%
test2 128 12.8%
test3 249 24.9%
test4 231 23.1%
test5 267 26.7%

要素数 10 数値の場合

キー名 取得数 確率
1 107 10.7%
2 91 9.1%
3 103 10.3%
4 82 8.2%
5 103 10.3%
6 93 9.3%
7 103 10.3%
8 127 12.7%
9 94 9.4%
10 97 9.7%

要素数 10 文字列の場合

キー名 取得数 確率
test1 106 10.6%
test2 103 10.3%
test3 107 10.7%
test4 96 9.6%
test5 89 8.9%
test6 99 9.9%
test7 103 10.3%
test8 78 7.8%
test9 95 9.5%
test10 124 12.4%

要素数 20 数値の場合

キー名 取得数 確率
1 5035 5.035%
2 5051 5.051%
3 5050 5.05%
4 4951 4.951%
5 5148 5.148%
6 5082 5.082%
7 5073 5.073%
8 5022 5.022%
9 4922 4.922%
10 4983 4.983%
11 4870 4.87%
12 4929 4.929%
13 4897 4.897%
14 4924 4.924%
15 4993 4.993%
16 4951 4.951%
17 5056 5.056%
18 5024 5.024%
19 4965 4.965%
20 5074 5.074%

要素数 20 文字列の場合

キー名 取得数 確率
test1 6699 6.699%
test2 6560 6.56%
test3 3384 3.384%
test4 3383 3.383%
test5 6593 6.593%
test6 6684 6.684%
test7 6565 6.565%
test8 3331 3.331%
test9 6644 6.644%
test10 6785 6.785%
test11 2255 2.255%
test12 3359 3.359%
test13 6690 6.69%
test14 6740 6.74%
test15 3380 3.38%
test16 2193 2.193%
test17 6681 6.681%
test18 6640 6.64%
test19 3232 3.232%
test20 2202 2.202%
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1