IT教程 ·

从有序聚集随机取一个值,应该用什么方案?

percona-toolkit 之 【pt-query-digest】使用,percona-toolkit 之 【pt-query-digest】介绍,percona-toolkit 之 【pt-query-digest】介绍,percona-toolkit 之 【pt-query-digest】介绍

本日做了一个小试验,原由以下:

先在redis里组织了测试数据,以下:

> zadd my_zset_999 1 35570
(integer) 1
> zadd my_zset_999 2 40617
(integer) 1
> zadd my_zset_999 3 40956
(integer) 1
> zadd my_zset_999 4 41151
(integer) 1
>
> zrange my_zset_999 0 -1 WITHSCORES
1) "35570"
2) "1"
3) "40617"
4) "2"
5) "40956"
6) "3"
7) "41151"
8) "4"
>
> zrange my_zset_999 0 -1
1) "35570"
2) "40617"
3) "40956"
4) "41151"

测试要领就是很简单的盘算程序运转时候

$t1 = microtime(true);
// 代码片断
$t2 = microtime(true);
$t = $t2 - $t1;

要领1
zrange key 0 -1 掏出一切的值
array_rand() 从数组中随机掏出一个值

要领2
zcount key -inf +inf 盘算该鸠合有多少个元素(cnt)
rand(1, cnt) 生成一个随机数(random)
zrangebyscore key random random

要领3:对要领2的革新
zcard key 盘算该鸠合有多少个元素(cnt)
rand(1, cnt) 生成一个随机数(random)
zrangebyscore key random random

要领4:对要领1的革新
zrangebyscore key -inf +inf
array_rand() 从数组中随机掏出一个值

要领 1 和要领 4 都是先掏出有序鸠合的一切值,再随机掏出一个值;
要领 2 和要领 3 则是随机从有序鸠合中掏出一个值。

下面是各要领的运转时候对照。

要领 2 和要领 3,即 zcountzcard 的运转时候对照:

运转时候对照 要领2/zcount 要领3/zcard
第1次 0.0072240829467773 0.007314920425415
第2次 0.0057311058044434 0.0071389675140381
第3次 0.0065360069274902 0.0071680545806885
第4次 0.0047309398651123 0.0075440406799316
第5次 0.0058040618896484 0.0068428516387939
第6次 0.0068061351776123 0.0073769092559814
第7次 0.0070509910583496 0.0070638656616211
第8次 0.008112907409668 0.0076460838317871
第9次 0.0070209503173828 0.0067050457000732
第10次 0.0069761276245117 0.0073142051696777

能够看出 zcountzcard 的波动大,且用时长,所以镌汰要领2,这是由于 zcard 的时候复杂度是 O(1),而 zcount 的时候复杂度是 O(log(N))

要领 1 和要领 3,即 zrangezrangebyscore 的运转时候对照:

运转时候对照 要领1/zrange 要领3/zrangebyscore
第1次 0.0076210498809814 0.0040271282196045
第2次 0.0066070556640625 0.0056281089782715
第3次 0.0062861442565918 0.0061671733856201
第4次 0.0070350170135498 0.0064809322357178
第5次 0.0070219039916992 0.0068569183349609

能够看出要领 2 比要领 1 要快一些。那如果把要领 1 改成用 zrangebyscore 掏出一切值,再随机取元素呢,也就是要领 4,再比较要领 4 和要领 3 的运转时候:

运转时候对照 要领4/zrangebyscore掏出数组,随机掏出1一个值 要领3/zrangebyscore依据随机数掏出一个值
第1次 0.0068261623382568 0.0075819492340088
第2次 0.0072751045227051 0.0073590278625488
第3次 0.0055849552154541 0.0072290897369385
第4次 0.0048110485076904 0.0075399875640869
第5次 0.0073840618133545 0.0075678825378418
第6次 0.0072331428527832 0.0072460174560547
第7次 0.007411003112793 0.0074880123138428
第8次 0.0062360763549805 0.007282018661499
第9次 0.0077290534973145 0.0074591636657715
第10次 0.0068199634552002 0.0074419975280762

能够看到要领 4 比要领 3 快一些,再用 ab 测试东西测一下

# 模仿100个并发用户,对一个资本发送100个要求。
ab -c 100 -n 100 url

要领 4 的测试效果以下:

Server Software:        nginx/1.15.11
Server Hostname:        127.0.0.1
Server Port:            80

Document Path:          test1.php
Document Length:        38 bytes

Concurrency Level:      100
Time taken for tests:   0.520 seconds
Complete requests:      100
Failed requests:        0
Non-2xx responses:      100
Total transferred:      23400 bytes
HTML transferred:       3800 bytes
Requests per second:    192.25 [#/sec] (mean)
Time per request:       520.161 [ms] (mean)
Time per request:       5.202 [ms] (mean, across all concurrent requests)
Transfer rate:          43.93 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       18   25   5.6     26      35
Processing:    41  219  87.1    219     359
Waiting:       41  219  87.4    219     359
Total:         60  245  92.3    246     393

Percentage of the requests served within a certain time (ms)
  50%    246
  66%    296
  75%    326
  80%    340
  90%    372
  95%    392
  98%    392
  99%    393
 100%    393 (longest request)

要领 3 的测试效果以下:

Server Software:        nginx/1.15.11
Server Hostname:        127.0.0.1
Server Port:            80

Document Path:          /test2.php
Document Length:        38 bytes

Concurrency Level:      100
Time taken for tests:   0.526 seconds
Complete requests:      100
Failed requests:        0
Non-2xx responses:      100
Total transferred:      23400 bytes
HTML transferred:       3800 bytes
Requests per second:    189.97 [#/sec] (mean)
Time per request:       526.390 [ms] (mean)
Time per request:       5.264 [ms] (mean, across all concurrent requests)
Transfer rate:          43.41 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       16   23   3.8     25      31
Processing:    36  216  89.5    220     372
Waiting:       36  216  89.2    220     372
Total:         54  239  92.9    245     403

Percentage of the requests served within a certain time (ms)
  50%    245
  66%    295
  75%    316
  80%    333
  90%    362
  95%    374
  98%    402
  99%    403
 100%    403 (longest request)

经由过程 Time taken for testsRequests per second 等效果,能够看出要领 4 比要领 3 的机能更高一些。

也就是先掏出一切元素,再随机掏出一个值 和 组织一个随机数掏出一个元素 这两种计划,前者更好一些。

到这里就完毕了吗?并没有~

终究效果就是不采纳有序鸠合这类数据结构了,用列表鸠合这类数据结构即可。由于有序鸠合 zset 还要组织 score 值,比方插进去元素,要查出最大的score值,再加 1。
既然需求只是从一堆元素中随机取一个值,用列表鸠合这类数据结构就可以满足所需了。

软工热身博客

参与评论