作为此前从未使用过Redis的晚期白中白(以下简称老白), 当使用Redis时极有可能会遇到一些常见的问题. 抛开尚远在天际的日常运维, 资源规划, 安全监控等等不谈, 在最具可感知性的内存占用高和响应速度慢方面, 老白的使用方式大抵是会出一点错的. 下面就来避一避雷.
众所周知, Redis因将数据存储于内存中而具备卓越的性能, 因此其数据访问速度极快. 然而, 考虑到机器内存远比MySQL之流所用的硬盘昂贵, 需要在使用时找到内存与磁盘之间的平衡.
在数据量较小时, 老白或许注意不到Redis内存的使用. 然而, 不用随着业务增长, 老白为了偷懒学习开发用的垃圾VPS(一下简称垃机)的512内存可能就会教他做人. 为了给垃机上的宝贝MySQL, MinIO等等留一点活路:
-
老白决定牺牲一下自己的开(偷)发(懒)体验
- 最简单直接的内存优化, 就是控制key的长度. 对于眼神和记性都不太好的老白来说, user_xxx_book_yyy_zzz_...这样的命名极具可读性, 一边set一边get的Redis一把梭开发模式也能极度减轻心智负担. 然而, 当如果key数量达到了百万级别, 那么过长的key名也会占用过多的内存空间. 减短key名就能节省大量内存, 这恐怕是最简单高效的省内存方式了. 例如, 原key为user:book:x, 则可以优化为u:bk:y. 看起来容易极了.
- 避免存储bigkey. 除了key本身的长度需要被控制外, key对应的value大小当然也应该被控制. bigkey不仅占内存, 而且会导致速度问题. 有人给老白的建议是:
- String的大小控制在10KB以下, 所以base64大图片拜拜~
- List/Hash/Set/ZSet: 元素数量控制在1万以下(别当垃圾桶用, 什么都装)
-
老白决定略微动一动脑子
- Redis提供了String/List/Hash/Set/ZSet五种数据结构, 但事实上底层的结构更多, 如有ziplist等等. Redis如此设计以节约宝贵的内存, 底层类型会自动转换. 所以, 以Hash为例, 将Hash子key数控制在512以下+子value控制在64Byte以下, 可以避免它从高效的ziplist转换成真hashtable. (或者可以去设置hash-max-ziplist-value和hash-max-ziplist-entries)
老白的脑子有些过载; let's call it a day.