控制 key 的长度
尽量使用简洁明了的 key 名称,避免使用过长的 key。
使用缩写或约定俗成的命名规则,例如使用 user:id
代替 user:identifier
。
对于经常查询的 key,可以适当牺牲可读性以缩短长度。
使用 Redis 的 INFO keyspace
命令监控数据库中 key 的长度分布,找出过长的 key 进行优化。
可以编写脚本定期检查 key 的长度,及时发现问题。
避免 bigkey
bigkey 指的是那些存储数据量非常大的 key,这通常是由于存储了大量的元素(如大列表、大集合、大哈希表)或单个非常大的字符串值。
对 Bigkey 的操作可能会阻塞 Redis,影响其他操作的响应时间。
读写 Bigkey 需要更多的网络带宽,可能会造成网络拥堵。
在设计数据结构时,应该将大对象拆分成多个小对象。例如,可以将一个大列表拆分成多个小列表,每个列表存储一定数量的元素。
对于非字符串的bigkey,比如hash list set zset,不要使用del删除,可以使用hscan、sscan、zscan方式渐进式删除。同时要注意防止bigkey过期时间自动删除问题。
设置 maxmemory和淘汰策略
maxmemory
配置项可以设置 Redis 实例可以使用的最大内存量。
当 Redis 达到这个限制时,它将根据配置的淘汰策略来决定如何处理新的写入请求。
配置 maxmemory
你可以在 Redis 的配置文件中通过以下方式设置 maxmemory
:
maxmemory <bytes>
这里的 <bytes>
是一个字节数,指定了 Redis 最多能使用的内存量。
例如,想要将 Redis 的最大内存限制为 1GB,可以设置:
maxmemory 1gb
我们也可以在运行时通过 Redis 的命令行接口(CLI)动态调整 maxmemory
:
CONFIG SET maxmemory <bytes>
淘汰策略
当 Redis 的内存使用达到 maxmemory
限制时,Redis 将开始根据所选的淘汰策略来删除旧的键,以便为新的键腾出空间。
以下是可用的淘汰策略:
noeviction
当 Redis 无法分配内存,并且
maxmemory
已经到达时,Redis 将直接返回错误给客户端(例如,OOM command not allowed
)。这是默认设置。allkeys-lru
当内存不足以容纳新加入的数据时,在键空间中移除最近最少使用的 key。这是最常用的策略之一。
allkeys-random
在所有 key 中随机移除某个 key。这种策略简单但可能不总是最优的选择,因为它可能会移除一些活跃度较高的 key。
volatile-lru
在设置了过期时间(TTL)的 key 中,移除最近最少使用的 key。这对于那些不需要持久化的数据来说是一个好的选择。
volatile-random
在设置了过期时间的 key 中随机移除某个 key。
volatile-ttl
在设置了过期时间的 key 中,移除 TTL 最短的 key,即优先移除即将过期的 key。
如果应用依赖于缓存数据的时效性,那么 volatile-lru
或 volatile-ttl
可能更适合。
如果应用对数据的访问模式较为均匀,则 allkeys-random
可能是更好的选择。
如果数据的访问模式遵循 LRU(最近最少使用)模式,则 allkeys-lru
是一个很好的选择。
同样地,我们可以在 Redis 的配置文件中设置淘汰策略:
maxmemory-policy <policy>
或者通过 CLI 动态设置:
CONFIG SET maxmemory-policy <policy>
开启 lazy-free 机制
Lazy-free 机制允许 Redis 在删除对象时,不是立即释放内存,而是将释放操作放入后台线程中异步执行。这样,即使操作涉及到大量数据的删除,也不会阻塞主线程。
要开启 lazy-free 机制,可以在 Redis 的配置文件(通常是 redis.conf
)中进行以下设置:
- lazyfree-lazy-eviction:当因为内存不足而需要淘汰 key 时,是否采用 lazy-free 机制。
- lazyfree-lazy-expire:当 key 过期时,是否采用 lazy-free 机制。
- lazyfree-lazy-server-del:当服务器因为某些原因需要删除 key 时(如 FLUSHDB、FLUSHALL),是否采用 lazy-free 机制。
- slave-lazy-flush:在从节点全量同步之前,是否先进行 lazy-free 的清空操作。
要开启所有 lazy-free 相关选项,可以设置如下:
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
slave-lazy-flush yes
使用长连接和连接池
连接池可以提供连接管理的功能,而长连接则可以减少连接的开销
不同的编程语言有不同的 Redis 客户端库,配置连接池的方式也有所不同。
只使用 db0
在单个连接上频繁操作不同数据库的数据时,每次操作前都需要执行 SELECT
命令来切换数据库,这会对 Redis 造成额外的性能负担。
在多个数据库中存储数据会增加数据错乱的风险。使用单一数据库可以有效降低这种风险,确保数据的完整性和一致性。
在Redis Cluster中,所有的数据都分布在db0中。这意味着,为了在集群环境中保持兼容性和一致性,推荐使用db0。这有助于在大规模分布式部署中保持数据的一致性和可管理性。