使用 Pipeline 访问 GeminiDB Redis
本文介绍了使用 Pipeline 访问 GeminiDB Redis 的原理以及注意事项。
Pipeline 简介
Redis 是一个请求/响应模型的服务,通常执行一个命令的流程为:
- 客户端发送命令到 Redis 服务器。
- Redis 服务器收到命令,排队等待处理。
- Redis 服务器执行命令。
- Redis 服务器返回结果给客户端。
上述4个步骤中,步骤1和4是IO操作,速度慢并且受网络状况影响,很容易成为瓶颈点。
为了减小网络开销,充分发挥 Redis 高性能的优势,可以使用 Pipeline 流水线执行命令。Pipeline 机制通过将一组 Redis 命令进行组装,一次发送多个命令,并在执行完成后一次性返回结果集,可以减少网络传输带来的开销,流程如下图所示:
上图中的 Pipeline 将3条命令封装成一组,只需要进行一次网络IO就完成了3条命令的执行。
除了网络层面的开销,使用 Pipeline 还可以减少客户端/服务器的 read()/write() 调用,提高程序的执行效率。
Pipeline 大小选择及注意事项
虽然使用 Pipeline 可以节省网络IO开销,但 Pipeline 并不是越大越好;使用 Pipeline 对程序性能的提升是有上限的,随着 Pipeline 逐渐增加,提高 Pipeline 的收益逐渐降低;如果一次组装的 Pipeline 数据量过大,一方面会导致客户端等待时间增加,另一方面,如果大的 Pipeline 导致 socket buffer 写满,可能会带来网络阻塞,反而引起性能下降;
根据经验,30 - 100 大小的 Pipeline 就已经可以充分发挥数据库的性能,具体最佳值与实际业务有关,建议以实际测试为准。
其它注意事项:
- Pipeline 不保证原子性,服务端在处理批量命令时,解析出多个单命令并按顺序执行,各个命令相互独立,服务端有可能在该过程中执行其他客户端的命令。某个命令执行失败不会影响其他命令的执行,如需原子性,需要使用事务或lua实现。
- 单次 Pipeline 的大小需要适当,大Pipeline可能会有OOM风险,也可能会造成网络阻塞;因为Redis 必须在处理完所有命令前,先缓存起所有命令的处理结果。这样会有内存的消耗,过大Pipeline造成内存上涨甚至OOM;对于单个命令数据长度较大的场景,需要适当的减小 Pipeline。
- 对于时延敏感的场景,不建议使用大 Pipeline,需要结合业务场景选择合适的 Pipeline大小。