Redis的使用建议

如何使用 Redis 更节省内存?

  • 控制 key 的长度
    • 例如,原有的 key 为 user:order:123,则可以优化为 u:od:123
  • 避免存储 bigkey
    • String:大小控制在 10KB 以下
    • List/Hash/Set/ZSet:元素数量控制在1万以下
  • 把 Redis 当作缓存使用
    • 尽可能地都设置「过期时间」
    • 让 Redis 中只保留经常访问的「热数据」
  • 客户端采用snappy、gzip等压缩算法,对键值压缩后存储到redis

如何持续发挥 Redis 的高性能?

  • 避免使用大value(10k以上就算大value,50k会记录)
  • 开启 lazy-free 机制
    • Redis在删除一个bigkey时,释放内存的耗时操作,将会放到后台线程中去执行
  • 不使用复杂度过高的命令
    • 复杂度过高消耗CPU时间更长,主线程中的其它请求只能等待
    • 避免执行例如 SORT、SINTER、SINTERSTORE、ZUNIONSTORE、ZINTERSTORE 等聚合类命令
  • 执行 O(N) 命令时,关注 N 的大小
    • 先查询数据元素的数量(LLEN/HLEN/SCARD/ZCARD)
    • 元素数量较少,可一次性查询全量数据
    • 元素数量非常多,分批查询数据(LRANGE/HASCAN/SSCAN/ZSCAN)
  • 关注 DEL 时间复杂度
    • List类型:执行多次 LPOP/RPOP,直到所有元素都删除完成
    • Hash/Set/ZSet类型:先执行 HSCAN/SSCAN/SCAN 查询元素,再执行 HDEL/SREM/ZREM 依次删除每个元素
  • 禁止使用 KEYS/FLUSHALL/FLUSHDB 命令
    • 从全表扫描变为点查/部分range, 虽然hash结构中field太多也会慢,但比keys性能提升一个到两个数量级
    • 会长时间阻塞 Redis 主线程,危害极大
    • SCAN 替换 KEYS
    • 4.0+版本可使用 FLUSHALL/FLUSHDB ASYNC,清空数据的操作放在后台线程执行

Redis的使用建议

  • 推荐:
    • 确定场景,是缓存(cache)还是存储型;
    • Cache的使用原则是:“无它也可,有它更强”;
    • 永远不要强依赖Cache,它会丢,也会被淘汰;
    • 优先设计合理的数据结构和逻辑;
    • 设计避免bigKey,就避免了80%的问题;
    • Keyspace能分开,就多申请几个Redis实例;
    • pubsub不适合做消息分发;
    • 尽量避免用lua做事务。
  • 不建议:
    • 我的服务对RT很敏感。>> 低RT能让我的服务运行的更好;
    • 我把存储都公用在一个redis里。>> 区分cache和内存数据库用法,区分应用;
    • 我有一个大排行榜/大集合/大链表/消息队列;我觉得服务能力足够了。>> 尽量拆散,服务能力不够可通过分布式集群版可以打散;
    • 我有一个特别大的Value,存在redis里,访问能好些。>> redis吞吐量有瓶颈。

常见问题

  • 当连接池被checkout完,就会爆没有连接的异常:"Could not get a resource from the pool",这是非常常见的错误,有恶性循环的逻辑在里面。比如说服务端返回的慢,连接池的连接就会创建的很快,用户很容易达到1万条,创建的连接越多,性能越差,返回越慢,服务容易血崩。

参考资料:缓存之王 | Redis最佳实践&开发规范&FAQ

posted @ 2021-11-20 11:15  爱定小闹钟  阅读(102)  评论(0)    收藏  举报