likes
comments
collection
share

【Redis】Redis 性能测试

作者站长头像
站长
· 阅读数 27

使用 Redis 官方提供的 redis-benchmark 工具可以对 Redis 进行性能测试。

Redis-benchmark 测试的命令有:

  • PING_INLINE:Ping 命令,使用 inline 协议。
  • PING_MBULK:Ping 命令,使用 multibulk 协议。
  • SET:设置一个 Key 的值。
  • GET:获取一个 Key 的值。
  • INCR:使一个 Key 的值加一。
  • LPUSH:将一个数从左边压入队列。
  • RPUSH:将一个数从右边压入队列。
  • LPOP:将一个数从左边出队。
  • RPOP:将一个数从右边出队。
  • SADD:向集合添加一个元素。
  • HSET:设置哈希表的一个字段的值。
  • SPOP:从集合取出一个元素。
  • ZADD:向 ZSET 添加一个元素。
  • ZPOPMIN:从 ZSET 取出最小元素。
  • LRANGE_100:返回列表左边前 100 个元素。
  • LRANGE_300:返回列表左边前 300 个元素。
  • LRANGE_500:返回列表左边前 500 个元素。
  • LRANGE_600:返回列表左边前 600 个元素。
  • MSET:原子地一次性设置多个 Key 的值。

inlinemultibulk 是 Reids 定义的数据解析协议。 inline 是老协议了,现在主要用在像 redis-cli 这种做简单的调试和处理中;程序客户端用的基本都是 multibulk 协议,它支持让空格和回车在 Redis 里面正确表达出来。

可以看到,只读的操作是 PINGGETLRANGE 这三个类别,其他操作都需要进行写操作。

单机测试

Docker 与 Host

对比一下 Docker 中与宿主机中 Redis 的性能差异,H 指 Host,C 指 Container。

参数:

  • 请求数量:100_000
  • 连接数量: 50
  • 数据大小: 3Byte
  • 保持连接: 开启
  • RDB  : 900 1; 300 10; 60 10000
  • AOF  : 关闭
  • 多线程 : 关闭

读操作对比

|          Test |  Host QPS | Container QPS | QPS ratio | Host Latency | Container Latency | La Ratio |
|--------------:|----------:|--------------:|----------:|-------------:|------------------:|---------:|
|         `GET` | 171821.30 |      42301.18 |      4.06 |        0.160 |             1.091 |    0.146 |
| `PING_INLINE` | 174520.06 |      40112.31 |      4.35 |        0.162 |             1.151 |    0.140 |
|  `PING_MBULK` | 154559.50 |      42176.30 |      3.66 |        0.188 |             1.092 |    0.172 |
|  `LRANGE_100` |  93196.65 |      34094.78 |      2.73 |        0.304 |             1.288 |    0.236 |
|  `LRANGE_300` |  30432.14 |      21427.04 |      1.42 |        0.897 |             1.726 |    0.519 |
|  `LRANGE_500` |  21399.53 |      15850.37 |      1.35 |        1.264 |             2.136 |    0.591 |
|  `LRANGE_600` |  18726.59 |      14269.41 |      1.31 |        1.542 |             2.284 |    0.675 |

GET 请求在主机中能达到十七万,在容器中能达到四万以上,算是比较好的成绩了,要注意我这里的 Host 实际上是 WSL2 虚拟机,因此容器指的是 WSL2 中的 Docker Container。

写操作对比

|          Test |  Host QPS | Container QPS | QPS ratio | Host Latency | Container Latency | La Ratio |
|--------------:|----------:|--------------:|----------:|-------------:|------------------:|---------:|
|         `SET` | 174216.03 |      42194.09 |      4.12 |        0.166 |             1.094 |    0.151 |
|        `INCR` | 194552.53 |      40799.68 |      4.76 |        0.146 |             1.134 |    0.128 |
|       `LPUSH` | 188679.25 |      41152.26 |      4.58 |        0.148 |             1.125 |    0.131 |
|       `RPUSH` | 190476.20 |      41169.21 |      4.62 |        0.147 |             1.123 |    0.130 |
|        `LPOP` | 176991.16 |      41017.23 |      4.31 |        0.157 |             1.128 |    0.139 |
|        `RPOP` | 176991.16 |      41237.11 |      4.29 |        0.155 |             1.123 |    0.138 |
|        `SADD` | 181488.20 |      40833.00 |      4.44 |        0.151 |             1.131 |    0.133 |
|        `HSET` | 165016.50 |      40600.89 |      4.06 |        0.165 |             1.134 |    0.145 |
|        `SPOP` | 176678.45 |      41407.87 |      4.26 |        0.154 |             1.114 |    0.138 |
|        `ZADD` | 214132.77 |      40633.89 |      5.26 |        0.133 |             1.135 |    0.117 |
|     `ZPOPMIN` | 173310.22 |      41390.73 |      4.18 |        0.161 |             1.116 |    0.144 |
|       `LPUSH` | 158730.16 |      40650.41 |      3.90 |        0.184 |             1.137 |    0.161 |
|        `MSET` | 138121.55 |      38565.37 |      3.58 |        0.312 |             1.203 |    0.259 |

写操作的差异更加明显,所以 Redis 最好是不要部署在容器中,平时拿来练手就可以。

为什么不补充 Windows 真机的测试结果呢?是因为 Redis 在 Win 下表现并不是特别好,速度差不多只有 Docker 的一倍,比 WSL 还差。

Rdb 开关对比

对比一下 Rdb 开启与关闭的速度差异。

参数:

  • 请求数量:100_000
  • 连接数量: 50
  • 数据大小: 3Byte
  • 保持连接: 开启
  • RDB  : 900 1; 300 10; 60 10000 或 关闭
  • AOF  : 关闭
  • 多线程 : 关闭

读操作速度基本相同就不用看了,重点关注写操作:

|    Test |      QPS |  RDB QPS | QPS ratio | Latency | RDB Latency | La Ratio |
|--------:|---------:|---------:|----------:|--------:|------------:|---------:|
|     SET | 37664.79 | 37147.11 |     1.013 |   1.236 |       1.252 |    0.987 |
|    INCR | 36995.93 | 36995.93 |     1.000 |   1.258 |       1.254 |    1.003 |
|   LPUSH | 35549.23 | 37119.52 |     0.957 |   1.312 |       1.255 |    1.045 |
|   RPUSH | 36523.01 | 36656.89 |     0.996 |   1.277 |       1.269 |    1.006 |
|    LPOP | 35893.75 | 35919.54 |     0.999 |   1.299 |       1.296 |    1.002 |
|    RPOP | 36630.04 | 36549.71 |     1.002 |   1.275 |       1.273 |    1.001 |
|    SADD | 36429.88 | 36913.99 |     0.986 |   1.278 |       1.259 |    1.015 |
|    HSET | 36114.12 | 36643.46 |     0.985 |   1.288 |       1.268 |    1.015 |
|    SPOP | 36764.71 | 36710.72 |     1.001 |   1.267 |       1.266 |    1.000 |
|    ZADD | 36179.45 | 35932.45 |     1.006 |   1.283 |       1.294 |    0.991 |
| ZPOPMIN | 36643.46 | 36710.72 |     0.998 |   1.268 |       1.266 |    1.001 |
|   LPUSH | 36205.65 | 36205.65 |     1.000 |   1.285 |       1.282 |    1.002 |
|    MSET | 34806.82 |  34566.2 |     1.006 |   1.341 |       1.351 |    0.992 |
|     Avg |        - |        - |     0.998 |       - |           - |    1.003 |

可以看出,二者速度差异并不明显,因为 Rdb 本来就不是即时快照,基本不会对性能造成太多影响。

AOF 开关对比

对比一下 AOF 开启与关闭的差异,还有各种模式的差异。

参数:

  • 请求数量:500_000
  • 连接数量: 50
  • 数据大小: 3Byte
  • 保持连接: 开启
  • RDB  : 900 1; 300 10; 60 10000
  • AOF  : 关闭 / no / everysec / always
  • 多线程 : 关闭

QPS

|    TEST |      OFF |       NO | Every Sec |   Always |                     Ratio |
|--------:|---------:|---------:|----------:|---------:|--------------------------:|
|     SET | 36683.79 | 30829.94 |  31098.40 |  2778.40 | 13.20 : 11.10 : 11.19 : 1 |
|    INCR | 36435.18 | 28082.00 |  31293.03 |  5991.11 |  6.08 :  4.69 :  5.22 : 1 |
|   LPUSH | 35803.79 | 27997.09 |  30644.77 |  3421.54 | 10.46 :  8.18 :  8.96 : 1 |
|   RPUSH | 35270.88 | 27942.33 |  30994.30 |  2879.06 | 12.25 :  9.71 : 10.77 : 1 |
|    LPOP | 32731.08 | 27311.96 |  30929.11 |  2377.05 | 13.77 : 11.49 : 13.01 : 1 |
|    RPOP | 32632.82 | 27783.95 |  31135.19 |  2792.09 | 11.69 :  9.95 : 11.15 : 1 |
|    SADD | 32918.56 | 33200.53 |  36480.37 | 37103.00 |  0.89 :  0.89 :  0.98 : 1 |
|    HSET | 29647.20 | 28494.90 |  30847.06 |  6031.22 |  4.92 :  4.72 :  5.11 : 1 |
|    SPOP | 32754.67 | 34698.12 |  36710.72 | 37094.74 |  0.88 :  0.94 :  0.99 : 1 |
|    ZADD | 32356.18 | 35714.29 |  36093.27 | 35844.86 |  0.90 :  1.00 :  1.01 : 1 |
| ZPOPMIN | 32877.43 | 36129.78 |  36659.58 | 36648.83 |  0.90 :  0.99 :  1.00 : 1 |
|   LPUSH | 33064.41 | 30415.48 |  30723.85 |  6216.04 |  5.32 :  4.89 :  4.94 : 1 |
|    MSET | 33824.92 | 27719.26 |  28282.14 |  5615.39 |  6.02 :  4.94 :  5.04 : 1 |

时延:

|    TEST |   OFF |    NO | Every Sec | Always | Ratio                   |
|--------:|------:|------:|----------:|-------:|:------------------------|
|     SET | 1.269 | 1.522 |     1.509 | 17.893 | 1 : 1.20 : 1.19 : 14.10 |
|    INCR | 1.276 | 1.667 |     1.500 |  8.238 | 1 : 1.31 : 1.18 :  6.46 |
|   LPUSH |   1.3 | 1.673 |     1.532 | 14.494 | 1 : 1.29 : 1.18 : 11.15 |
|   RPUSH |  1.32 | 1.677 |     1.514 | 17.247 | 1 : 1.27 : 1.15 : 13.07 |
|    LPOP | 1.421 | 1.715 |     1.516 | 20.934 | 1 : 1.21 : 1.07 : 14.73 |
|    RPOP | 1.426 | 1.688 |     1.507 | 17.781 | 1 : 1.18 : 1.06 : 12.47 |
|    SADD | 1.411 | 1.399 |     1.275 |  1.253 | 1 : 0.99 : 0.90 :  0.89 |
|    HSET | 1.565 | 1.644 |     1.519 |  8.189 | 1 : 1.05 : 0.97 :  5.23 |
|    SPOP | 1.417 | 1.338 |     1.267 |  1.255 | 1 : 0.94 : 0.89 :  0.89 |
|    ZADD | 1.435 | 1.302 |     1.289 |  1.299 | 1 : 0.91 : 0.90 :  0.91 |
| ZPOPMIN | 1.411 | 1.285 |     1.267 |  1.268 | 1 : 0.91 : 0.90 :  0.90 |
|   LPUSH | 1.407 | 1.542 |     1.526 |  7.942 | 1 : 1.10 : 1.08 :  5.64 |
|    MSET | 1.381 | 1.704 |     1.671 |  8.799 | 1 : 1.23 : 1.21 :  6.37 |

可以看到 Every Second 模式与关闭 AOF 的效果接近,反倒是 NO 模式性能比 Every Second 效果要差,这一点比较出乎我的意料,可能是容器的系统 flush 机制稍有不同吧,接下来有时间会进行时机测试对比验证。

TODO: 实机验证 no 模式是否比 every second 差。

可以看到 always 模式简直致命,并发度甚至可以拿事务型数据库来与之争锋了,因此非常不推荐使用 always 模式。

主从复制测试

主要是测试主从复制模式下,Master 的读写性能与单机的读写性能差异。

|        TEST |    M QPS |      QPS | QPS Ratio | M latency | latency | La Ratio |
|------------:|---------:|---------:|----------:|:----------|:--------|---------:|
| PING_INLINE | 39525.69 | 37523.45 |     1.053 | 1.175     | 1.24    |    0.948 |
|  PING_MBULK | 38565.37 | 39416.63 |     0.978 | 1.197     | 1.173   |    1.020 |
|         GET | 39635.36 | 42229.73 |     0.939 | 1.164     | 1.094   |    1.064 |
|  LRANGE_100 | 32701.11 | 33322.23 |     0.981 | 1.348     | 1.323   |    1.019 |
|  LRANGE_300 | 20863.76 | 21253.99 |     0.982 | 1.763     | 1.756   |    1.004 |
|  LRANGE_500 | 15586.04 | 15659.25 |     0.995 | 2.173     | 2.197   |    0.989 |
|  LRANGE_600 | 13791.20 | 14409.22 |     0.957 | 2.36      | 2.311   |    1.021 |
|         SET | 30797.66 | 35087.72 |     0.878 | 1.53      | 1.333   |    1.148 |
|        INCR | 32509.75 | 35360.68 |     0.919 | 1.447     | 1.318   |    1.098 |
|       LPUSH | 31635.56 | 34411.56 |     0.919 | 1.491     | 1.359   |    1.097 |
|       RPUSH | 31036.62 | 34891.84 |     0.890 | 1.519     | 1.341   |    1.133 |
|        LPOP | 30543.68 | 34129.69 |     0.895 | 1.542     | 1.369   |    1.126 |
|        RPOP | 29877.50 | 34506.55 |     0.866 | 1.577     | 1.354   |    1.165 |
|        SADD | 39047.25 | 41034.06 |     0.952 | 1.183     | 1.128   |    1.049 |
|        HSET | 29214.14 | 34258.31 |     0.853 | 1.615     | 1.36    |    1.188 |
|        SPOP | 41254.12 | 40600.89 |     1.016 | 1.121     | 1.138   |    0.985 |
|        ZADD | 39385.59 | 38744.67 |     1.017 | 1.173     | 1.192   |    0.984 |
|     ZPOPMIN | 37285.61 | 39077.77 |     0.954 | 1.239     | 1.179   |    1.051 |
|       LPUSH | 31172.07 | 33863.87 |     0.921 | 1.513     | 1.379   |    1.097 |
|        MSET | 26123.30 | 30093.29 |     0.868 | 1.824     | 1.567   |    1.164 |

可以看到,对于大部分写操作,大概有 10% 的性能损失。

集群测试

测试集群模式与单例模式下性能的差异。由于集群采用的是 Docker 内网集群,因此测试都转移到容器内进行测试。或许是少了 Docker 的网络转发,测试速度相比于在宿主机测试快了非常多。

|        TEST |     C QPS |       QPS | QPS Ratio | C latency | latency | La Ratio |
|------------:|----------:|----------:|----------:|:----------|:--------|---------:|
| PING_INLINE | 199203.20 | 124533.01 |     1.600 | 0.113     | 0.227   |    0.498 |
|  PING_MBULK | 200000.00 | 120192.30 |     1.664 | 0.115     | 0.249   |    0.462 |
|         GET | 199600.80 | 132978.73 |     1.501 | 0.107     | 0.206   |    0.519 |
|  LRANGE_100 | 133155.80 |  63211.12 |     2.107 | 0.186     | 0.438   |    0.425 |
|  LRANGE_300 |  57077.62 |  27225.70 |     2.096 | 0.41      | 0.989   |    0.415 |
|  LRANGE_500 |  44385.27 |  19531.25 |     2.273 | 0.574     | 1.386   |    0.414 |
|  LRANGE_600 |  36324.01 |  17009.70 |     2.135 | 0.667     | 1.6     |    0.417 |
|         SET | 200000.00 | 152905.20 |     1.308 | 0.171     | 0.196   |    0.872 |
|        INCR | 200000.00 | 158478.61 |     1.262 | 0.158     | 0.172   |    0.919 |
|       LPUSH | 200000.00 | 183150.19 |     1.092 | 0.18      | 0.155   |    1.161 |
|       RPUSH | 200000.00 | 155038.77 |     1.290 | 0.171     | 0.182   |    0.940 |
|        LPOP | 200000.00 | 134408.59 |     1.488 | 0.174     | 0.207   |    0.841 |
|        RPOP | 200000.00 | 151975.69 |     1.316 | 0.191     | 0.199   |    0.960 |
|        SADD | 200000.00 | 125313.29 |     1.596 | 0.12      | 0.224   |    0.536 |
|        HSET | 199600.80 | 142653.36 |     1.399 | 0.193     | 0.244   |    0.791 |
|        SPOP | 199600.80 | 121065.38 |     1.649 | 0.116     | 0.227   |    0.511 |
|        ZADD | 200000.00 | 140449.44 |     1.424 | 0.125     | 0.198   |    0.631 |
|     ZPOPMIN | 199600.80 | 132626.00 |     1.505 | 0.117     | 0.21    |    0.557 |
|       LPUSH | 199600.80 | 160771.70 |     1.242 | 0.189     | 0.187   |    1.011 |
|        MSET | 133333.33 | 109409.20 |     1.219 | 0.312     | 0.395   |    0.790 |

可以看到,集群模式下,性能要优于单例模式非常多。