Redis缓存使用规范参考集


本文收集了业界一些基于Redis的使用规范,为大家的使用提供一个参考;不过在开始之前,先对其的使用概况做一个介绍。
Redis(REmote DIctionary Server)是一个基于 C 语言开发的开源 NoSQL 数据库,与传统数据库不同的是,Redis 的数据是保存在内存中的(内存数据库,支持持久化),因此读写速度非常快,被广泛应用于分布式缓存方向。并且Redis存储的是 KV 键值对数据。
为了满足不同的业务场景,Redis 内置了多种数据类型实现(比如 String、Hash、Sorted Set、Bitmap、HyperLogLog、GEO);并且其还支持事务、持久化、Lua 脚本、多种开箱即用的集群方案(Redis Sentinel、Redis Cluster)。

Redis 数据类型概览
Redis 没有外部依赖,Linux 和 OS X 是其开发和测试最多的两个操作系统,官方推荐生产环境使用 Linux。
Redis 为什么这么快
其内部做了非常多的性能优化,比较重要的有下面 3 点:
1.基于内存,内存的访问速度是磁盘的上千倍;
2.基于 Reactor 模式设计开发了一套高效的事件处理模型,主要是单线程事件循环和 IO 多路复用;
3.内置了多种优化过后的数据类型/结构实现,性能非常高。
下面这张图片总结的挺不错的,出自 Why is Redis so fast?。

分布式缓存常见的技术选型方案有哪些
分布式缓存的话,比较老牌同时也是使用的比较多的还是 Memcached 和 Redis。不过现在基本没有看过还有项目使用 Memcached 来做缓存,都是直接用 Redis。
Memcached 是分布式缓存最开始兴起的那会比较常用的;后来随着 Redis 的发展,大家慢慢都转而使用更加强大的 Redis 了。
有一些大厂也开源了类似于 Redis 的分布式高性能 KV 存储数据库,例如,腾讯开源的 Tendis,其基于知名开源项目 RocksDB作为存储引擎,100% 兼容 Redis 协议和 Redis 4.0 所有数据模型。
不过从 Tendis 这个项目的 Github 提交记录可以看出,其开源版几乎已经没有被维护更新了,加上其关注度并不高,使用的公司也比较少。因此不建议使用 Tendis 来实现分布式缓存。
目前比较业界认可的 Redis 替代品还是下面这两个开源分布式缓存:
Dragonfly:一种针对现代应用程序负荷需求而构建的内存数据库,完全兼容 Redis 和 Memcached 的 API,迁移时无需修改任何代码,号称全世界最快的内存数据库。
KeyDB:Redis 的一个高性能分支,专注于多线程、内存效率和高吞吐量。
不过还是建议分布式缓存首选 Redis,毕竟经过这么多年的生产考研,生态也这么优秀,资料也很全面。说一下 Redis 和 Memcached 的区别和共同点
现在公司一般都是用 Redis 来实现缓存,而且 Redis 自身也越来越强大了!不过了解 Redis 和 Memcached 的区别和共同点,有助于在做相应的技术选型的时候能够做到有理有据!
共同点:
都是基于内存的数据库,一般都用来当做缓存使用。
都有过期策略。
两者的性能都非常高。
区别:
1、Redis 支持更丰富的数据类型(支持更复杂的应用场景)。它不仅仅支持简单的 k/v 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。Memcached 只支持最简单的 k/v 数据类型。
2、Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而 Memcached 把数据全部存在内存之中。
3、Redis 有灾难恢复机制。 因为可以把缓存中的数据持久化到磁盘上。
4、Redis 在服务器内存使用完之后,可以将不用的数据放到磁盘上。但是,Memcached 在服务器内存使用完之后,就会直接报异常。
5、Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 Redis 目前是原生支持 cluster 模式的。
6、Memcached 是多线程,非阻塞 IO 复用的网络模型;Redis 使用单线程的多路 IO 复用模型(Redis 6.0 针对网络数据的读写引入了多线程)。
7、Redis 支持发布订阅模型、Lua 脚本、事务等功能,而 Memcached 不支持。并且 Redis 支持更多的编程语言。
8、Memcached 过期数据的删除策略只用了惰性删除,而 Redis 同时使用了惰性删除与定期删除。
相信看了上面的对比之后,已经没有什么理由可以选择使用 Memcached 来作为自己项目的分布式缓存了。
为什么要用Redis作缓存
下面主要从“高性能”和“高并发”这两点来回答这个问题。
1、高性能
假如用户第一次访问数据库中的某些数据的话,这个过程是比较慢,毕竟是从硬盘中读取的。但是,如果说,用户访问的数据属于高频数据并且不会经常改变的话,那么我们就可以很放心地将该用户访问的数据存在缓存中。
2、高并发
一般像 MySQL 这类的数据库的 QPS 大概都在 1w 左右(4 核 8g),但是使用 Redis 缓存之后很容易达到 10w+,甚至最高能达到 30w+(就单机 Redis 的情况,Redis 集群的话会更高)。
QPS(Query Per Second):服务器每秒可以执行的查询次数;
由此可见,直接操作缓存能够承受的数据库请求数量是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。进而也就提高了系统整体的并发。
什么是 Redis Module?
Redis 从 4.0 版本开始,支持通过 Module 来扩展其功能以满足特殊的需求。这些 Module 以动态链接库(so 文件)的形式被加载到 Redis 中,这是一种非常灵活的动态扩展功能的实现方式,值得借鉴学习!大家都可以基于 Redis 去定制化开发自己的 Module,比如实现搜索引擎功能、自定义分布式锁和分布式限流。目前被 Redis 官方推荐的 Module 有:
RediSearch:用于实现搜索引擎的模块。
RedisJSON:用于处理 JSON 数据的模块。
RedisGraph:用于实现图形数据库的模块。
RedisTimeSeries:用于处理时间序列数据的模块。
RedisBloom:用于实现布隆过滤器的模块。
RedisAI:用于执行深度学习/机器学习模型并管理其数据的模块。
RedisCell:用于实现分布式限流的模块。
……
关于 Redis 模块的详细介绍,可以查看官方参考文档。
喜马拉雅Redis与Pika缓存使用规范
作者:喜马拉雅 董道光
宣言:缓存不是万金油,更不是垃圾桶!
缓存作为喜马拉雅至关重要的基础组件之一,每天承载着巨大的业务请求量。一旦缓存出现故障,对业务的影响将非常严重。因此,确保缓存服务的稳定和高效运行始终是我们的重要目标。下面是对喜马缓存历史故障复盘后总结的一套缓存使用规范,在此分享给大家,希望小伙伴们能在缓存选型和使用的过程中少踩坑。
1. 缓存选型
1.1 缓存类型介绍
喜马线上缓存类型主要有 4 种:
1. redis 主从模式:官方原版
2.codis-redis:豌豆荚开源,redis 集群解决方案
3.云数据库 redis:redis-cluster 容器化部署
4.xcache:基于 codis、pika、redis 自研的一套海量 KV 存储解决方案
1.2 缓存使用模式介绍
使用模式主要分为 2 种:
1.cache 模式:数据不需要持久化,实例恢复不需要加载数据,扩缩容不需要迁移数据
2.store 模式:数据需要持久化,实例恢复需要加载数据,扩缩容需要迁移数据
下面是对各种类型缓存做了简单对比:

2. 缓存使用军规
2.1 缓存类型使用规范
1)redis 集群模式首选云数据库 redis,海量 KV 存储首选 xcache
云数据库 redis 采用官方 redis cluster 模式,容器化部署,支持故障自动恢复和弹性伸缩,是当前 redis 集群的主推方案,但不支持数据持久化,如果必须要做数据持久化,并且对延时要求非常高,可以使用 codis redis。数据量非常大,并且对延时要求不是特别高,可以选择 xcache。
2)redis 不要当 db 使用,如果数据一定要做持久化,可以选择 xcache
redis 当 db 使用,故障恢复数据很慢,严重影响 SLA。并且如果主从全部挂掉,slave 机器无法恢复时,数据就会完全丢失。xcache 天然支持数据持久化。
3)不要使用客户端分片模式
客户端分片模式不具备高可用和弹性伸缩能力,建议使用真正的集群模式,如 codis-redis、云数据库 redis、xcache。
4)集群模式不支持 lua、redisson 客户端,如果业务必须使用,只能选择 redis 主从模式。
5)单节点容量阀值
redis 单节点容量不要超过 10GB,xcache 单节点容量不要超过 200GB;redis 单节点容量太大时,实例重启会比较慢,影响恢复时长。
2.2 键值设计规范
1)key 尽量保持简洁性、可读性、可管理性
在保证语义的前提下,控制 key 的长度;以业务名 (或数据库名) 为前缀 (防止 key 冲突),用冒号分隔,比如业务名:表名:id;不要包含特殊字符。
2)拒绝 bigkey,防止网卡流量过高、慢查询
string 类型控制在 10KB 以内,hash、list、set、zset 元素个数不要超过 5000。
3)避免热点 key
热 key 会导致数据倾斜,以及单节点压力过大。建议业务侧将热 key 打散。
4)控制 key 生命周期
缓存不是垃圾桶,最好对 key 都设置 ttl,并且将 key 的 ttl 打散,避免 key 集中过期。
2.3 命令使用规范
1)慎用全量操作命令
禁用 `keys *` 命令,尽量不使用 hgetall、smembers 等命令。在获取 key 下的多个元素时,使用相应的 scan 命令,一次获取少量元素,分多次获取,建议一次 scan 不要超过 200 个。
2)控制 mset、mget、hmset、hmget、*scan、*range 等命令单次操作元素数量,建议不要超过 200
3)控制 pipeline 中命令的数量,建议不要超过 100
4)redis 删除 key 时,不要用 del 命令,使用 unlink 命令
del 一个大 key 会直接导致 redis 卡住。使用 unlink 命令可以异步删除 key,不会对 redis 主线程产生影响,因此也不会影响业务流量。
5)set 和 expire 命令合并成 setex 命令,减少服务端写压力。
6)evalsha 代替 eval
redis-cluster 集群中使用 evalsha 代替 eval,减少网络 IO,同时也减小 redis 网络 IO 压力提高性能。
2.4 业务缓存架构规范
1)redis 不要使用逻辑 db,只使用默认 db 0
可以通过实例隔离,不同业务的数据保存到不同的实例中。(只有 redis 主从可以选择逻辑 db,集群模式默认都使用 db0)。
2)避免多业务复用同一缓存资源
不同业务的数据使用不同的集群,S 级应用不要和 B 级应用混用,过多业务复用同一资源要做拆分。业务尽量提供 rpc 接口给其它业务调用,而不是直接让其它业务访问数据源(如一个业务写,一个业务读)。
3)xcache 尽量使用 string 类型
xcache 支持 string,hash,ehash,list,set,zset 六种数据类型,ehash 数据类型是对 hash 数据类型的扩展,支持对 field 设置过期时间。xcache 中 string 类型是速度最快的,其他数据类型都是由 string 进行组合变换而实现,六种数据的性能如下:
string > hash > set > ehash > list > zset
建议:尽量使用 string 类型
4)减少 lua 脚本使用
集群模式对 lua 支持有限制,必须保证 lua 中操作的 key 被 sharding 到同一个节点。所以尽量减少对 lua 的使用。
5)lua 脚本中不跑复杂逻辑
复杂逻辑放在业务代码中,而不是 lua 脚本中。
6)采用高效序列化方法和压缩方法
为了节省内存,如果 value 较大时,可以使用压缩工具(如 snappy 或 gzip),把数据压缩后再写入 redis。
7)避免批量任务、定时任务、周期任务流量太大影响在线业务
批量任务、定时任务、周期任务业务上要做限速。
8)业务变更,存储流量模型变化要先评估
业务模型变化,QPS、容量增加,O (N) 命令增多等都要先评估当前缓存是否抗的住,做到灰度上线,持续观察(尤其是流量高峰期)。
9)不用的资源尽早申请回收
休眠资源回收不仅可以降低业务的存储成本,还可以把资源分配给真正需要的业务,可谓是双赢。
3. 优化参考
实施流量压缩方案、清理无效数据、治理实例 TTL、下线无用实例等优化措施,涉及流量复制、流量放大、数据迁移、数据在线压缩与解压缩、数据定向清理与定向指定 TTL、扫描分析 Key 最后访问时间等工具辅助方案落地。
1、清理未使用的实例
有的业务下线了但实例还在,需要清理这类实例。这个是最容易实现的,最快能优化的,通过采集 Redis Metrics 数据,筛出长期 QPS 非常低的实例(集群版本 Redis, 自身也会有 ping 等保活访问),观测连接数据等,和业务确认并释放。
2、实例降配:提高内存使用率
各种因素,导致实际使用的内存,和申请的内存差别较大,导致使用率上不去,存在内存浪费。比如:
业务容量预估偏差导致的内存长期使用率偏低
业务进入稳定期,内存不在快速增长,内存使用率较稳定
这些场景需要通过降配,将使用率至少稳定在 70% 左右。降配时,需要注意如下:
集群降配到主从,注意业务端的链接模式是否兼容
大集群降配到小集群,注意是否有大 key 限制
大集群降配到小集群,注意数据倾斜问题导致小集群节点塞满了
大集群降配到小集群,注意节点数的变化,比如 128 节点降配到 32 节点,性能落差会非常大。
除了内存使用率,降配时还需要注意带宽的使用情况,
降配时,尽量在同等容量规格的情况下,选择节点数最多的规格,节点数越多性能越好。比如同样是 256GB 的,优先选择 128 节点 2GB 的集群,不要选择 32 节点 * 8GB 的集群。
降配时,会存在连接闪断抖动,尽量在业务低峰期进行。
3、使用场景打标,允许部分场景内存用满
使用 Redis 的情形可分类为【被动缓存】、【非被动缓存】两类场景。
【被动缓存】:典型的缓存场景,用来挡在 MySQL 前面抗流量(先请求 Redis 拿数据,没拿到则到 MySQL 里取数据,设置到 Redis),Redis 内存用满时也不用扩容,设置好驱逐策略即可。
【非被动缓存】:搜广推场景的特征数据,Redis 里的数据是实时流、离线等业务主动写入的。如果内存到了 90% 告警线,需要及时扩容,避免重要数据被驱逐
通过合理的区分不同 Redis 实例的使用场景,制定不一样的告警策略,允许部分场景 Redis 使用率 100%,可进一步提高整个 Redis 的内存使用率。实施时需要注意如下:
被标记为【被动缓存】的实例,需要明确所有的 key 都设置了 TTL ,明确允许所有的 key 都允许被驱逐。否则会导致内存用满,然后写入被拒的情况。
被标记为【被动缓存】的实例,在主从架构中,可关闭主服务的 aof(aof 关闭涉及到 config rewrite 会阻塞主进程,会对线上集群产生影响,应尽量在业务低峰期操作),降低数据驱逐时的性能影响,提高性能。
4、合理设置 TTL
使用 Redis 时,99% 的场景 Key 是可过期删除的。只不过,不同的场景对 TTL 的要求是不一样的,这个需要业务自行判断。但是 infra 可以把大实例的 TTL 比例全部捞出来从大到小依次过一遍。
有的实例 32G 没有设置 TTL ,实际活跃实际只有 32G 不到,通过设置合理的 TTL ,可以优化 50% 的内存。
有的实例 TTL 设置了一年,实际活跃数据只有半年,或者一个月
以上都可以通过设置合理的 TTL,来优化内存使用。实施时需要注意如下:
实施前需要采集 Redis Metrics 数据,筛出内存规格大,未设置 TTL key 占比高的实例。
大部分场景其实业务也不知道合理的 TTL 是多少。所以需要准备好 Key 的访问时间(最后一次访问)分布情况,这个需要 scan 分析,后文会提到这个工具。提供给业务做 TTL 决策。
有了预期的 TTL 后,需要将所有的数据都刷一遍。所以需要一个刷 TTL 的运维工具脚本,同时可以指定清理最后一次访问距今时间的数据。
5、清理历史数据
部分业务把 Redis 当持久化存储,但是中间数据结构发生过变化,导致历史无用数据占用内存空间。这个场景和 5、合理设置 TTL 有点类似,同样需要:
准备好 Key 的访问时间(最后一次访问)分布情况,提供给业务做数据清理决策。
有了预期的清理逻辑后,需要一个清理 Key 的运维工具脚本,功能包含【指定 key 前缀清理】、【指定清理最后一次访问距今时间的数据 Key】。
6、改进 kv 结构
部分业务把整个大的 json 对象一股脑的存到 Redis ,其实部分字段用不着,可以裁剪 value 的大小,减少内存使用。
部分场景,比如判断用户设备是否是新设备,采用 Bloomfilter 相比 String,相同数据规模,可以节省 90% 以上的内存。
7、定期 scan, 释放已过期的内存
因为 Redis 已过期 key 的清理策略,是惰性删除的(已经过期的 key ,只有被访问过或者 hz 扫描到才会被删除),所以通过定期使用 SCAN 命令扫描键空间并手动删除已过期的键,可以更精细地管理 Redis 内存,提高系统的稳定性和资源利用效率。实施时需要注意:选择在业务低峰期进行,控制好 SCAN 的速率,尽量减少对线上业务的影响。
8、降低可用性
在 dev、qa 环境中,可通过如下措施来进一步降低成本:
合并小实例,部分实例已经是最小规格,但是内存使用率只有不到 10%,这种情况下,可以通过小实例合并来缩减成本
在 dev、qa 等对可用性要求不高的环境里,可通过对集群、主备版本,降配到单实例规格降低成本。
9、压缩 value
选择合适的压缩算法,对 value 进行压缩后存储。部分场景的压缩率可达 50%~80%,意味着部分实例至少可优化 50% 左右的内存。因为这个方案实施比较复杂,所以尽量挑选 100GB 以上的实例进行优化,性价比较高。适合压缩的特征如下:
value 大(100b 以上),字符重复度高
有3个主流的压缩算法,gzip 、zstd、snappy。测试下来 ,不同的压缩算法特点如下:
gzip 、zstd: 这两个压缩和解压缩表现都不错,性能比较均衡。在不同的 value 特征的压缩 & 解压缩性能表现差异不大
snappy:压缩比较耗时,但是解压缩非常快。
对 852k 的一个 user_profile 数据做了一个测试,(不同大小的数据性能差异较大,最终应该以线上数据流量的测试结果为准) 测试方法:运行 100 次取均值
snappy
压缩耗时:122722us
压缩率:22.60%
解压耗时:49us
gzip
压缩耗时:39821us
压缩率:15.79%
解压耗时:3521us
zstd
压缩耗时:6953us
压缩率:17.08%
解压耗时:3153us
最后 snappy 就直接否了,因为压缩的资延时不符合预期;然后不同的实例都验证下 gzip、zstd 哪个性能好就选择哪个。具体实施时需要注意如下:
1.准备好 Redis 流量复制的工具,复制线上流量进行 zstd、gzip 的压缩、解压缩性能测试,明确压缩率、压缩延时和解压缩延时数据。
2.定制 Redis 访问客户端,无缝兼容各种指令的 gzip 、zstd 压缩数据,做到应用端不用改代码,只需要升级客户端版本就可以完成压缩、解压缩兼容。
3.研发存量数据全量压缩的运维工具,这个工具支持指定压缩算法、支持指定 Key 前缀压缩、支持解压缩等。
4.注意开启压缩后,对应用 CPU 等资源消耗的的影响,读取延时普遍会增加 1~2ms 左右。
5.刷线上存量的数据压缩前,确保应用都更新到兼容压缩的 Redis 访问客户端了,然后对部分 key 灰度压测,观测线上情况,没有问题后在全量刷。发现问题后及时解压缩。
10、迁移到兼容 Redis 协议的磁盘存储项目
早期本着性能优先的原则,所有的 Redis 实例都是【内存型】。随着数据规模增大,内存资源占用会随之递增,Redis 存储成本大幅攀升。另一方面,随着业务的发展,当业务进入发展后期,数据量已经形成一定规模,而数据的访问频度则慢慢降下来,资源使用率普遍偏低。针对这类问题,可重新从性能、和成本综合评估业务更适合【内存型】、【磁盘型】的 Redis 实例。
内存型
优点:性能好(p99 延时很稳定)、扩展性好、支持水平伸缩
缺点:成本高
磁盘型
基于 RocksDB 实现的磁盘存储、兼容 Redis 协议的产品,社区里也有 pika、kvrocks 这类项目。
优点:成本低,是内存型的 16%。有容量起点,相比内存型,至少存储 64GB 以上才有性价比。
缺点:性能一般(p99 延时存在波动,突刺效应明显),是内存型的 70% 性能。且只支持垂直扩容,没法水平伸缩。
这个优化措施涉及到数据的迁移,且需要兼顾业务稳定性。所以实施起来比【压缩 Value】还要复杂,主要注意点如下:
1.如何筛选迁移到【磁盘型】的 Redis 实例?写请求低于 10k/s ,读请求低于 100k/s, 对 p99 时延要求不敏感,比如可以接受 avg 大于 0.5ms ,p99 5ms 的场景,且存储容量非常大 100GB 以上 ,而且预期存储容量会进一步增长。
2.采集好【磁盘型】的 Metrics ,做好监控观测。阿里云只给了基础的 Metrics,底层的数据指标,比如 RocksDB 层的、以及指令级的延时(对后面判断指令性能问题非常有帮助)、QPS 等都需要通过 info 指令拿到信息后自己解析采集。
3.准备好 Redis 流量复制工具,复制线上流量到【磁盘型】Redis 目标实例,对流量进行等比,加倍回放,对每个迁移的实例针对性的进行性能压测验证。确保覆盖每个指令的性能问题、兼容问题。
4.对【磁盘型】实例做好容量规划,QPS 增长评估。
5.使用 DTS 进行数据迁移时,确保原实例内存至少有 20% 的冗余,否则需要先扩容原实例在迁移。因为 DTS 是基于【Redis 主从复制这套逻辑】来进行同步的,同步时,缓冲区需要占用内存。
6.如果原实例的写入流量较大,DTS 迁移前,最好先调整下【 client-output-buffer-limit replica】、【repl-backlog-size 】、【DTS 收到 Master 的 RDB 后,立马回复 ACK 的开关】这些参数,避免同步反复失败。
Redis操作时几个低级错误
1、FLUSHALL 和 FLUSHDB
这两个命令会分别清空所有数据库或当前数据库中的所有数据。由于它们会删除大量数据,数据量大的时候会对性能产生明显影响;并且如果使用不当,可能会导致数据丢失。为了避免误操作,可以考虑在配置文件中禁用或重命名这些命令。
2、KEYS
这个命令用于查找所有匹配给定模式的键。这个命令会扫描整个键空间,可能会导致性能问题,因为它会锁定数据库直到搜索完成。一个比较好的替代是使用 SCAN 命令,它提供了一种逐步迭代 Redis 中的键的方式,而不会阻塞服务器。
3、CONFIG
这个命令允许客户端动态地修改 Redis 配置。出于安全考虑,应该避免使用此命令,因为这可能会被用来更改重要的配置,从而影响服务器的稳定性和安全性。Redis 配置建议最好都在 redis.conf 中直接配置好再启动,这是最佳实践。
4、MONITOR
这个命令用来实时监控 Redis 服务器接收到的命令。在高负载的情况下使用它可能会导致性能问题,因为它会增加 Redis 的输出缓冲区的内存使用,命令多的时候可能会造成缓冲区溢出。
5、直接删除 BIGKEY
当你发现 Redis 中存在 BIGKEY 的时候,二话不说就想用 DEL 将其干掉。在 Redis 中,直接删除 bigkey 会对性能产生负面影响。因为 Redis 是单线程处理请求的,删除 bigkey 会占用较长时间,从而阻塞其他请求的处理。
那么如果想要删除 bigkey 该怎么处理呢?
1.分批删除:可以尝试分批删除 bigkey 中的元素,例如使用 LREM 命令从列表中移除元素,或者使用 ZREM 命令从有序集合中移除元素。这样可以减少一次性删除大量元素对性能的影响。
2.使用 UNLINK 命令:在 Redis4.0 及以上版本中,可以使用 UNLINK 命令来异步删除 key。这个命令会将删除操作放入后台处理,不会立即释放内存,从而减少了对主线程的阻塞。
3.使用 SCAN 命令:如果需要删除多个 bigkey,可以使用 SCAN 命令配合 DEL 命令来分批次删除,以减少对服务器性能的影响。
4.使用 lazy-free 机制:在 Redis4.0 及以上版本中,可以开启 lazy-free 机制,使得内存释放操作在后台线程中进行,减少对主线程的影响。
5.避免创建 bigkey:最好的方法是避免创建 bigkey。设计应用程序时,应该尽量将数据分割成更小的块,这样可以提高性能并减少删除操作的复杂性。
6、动辄全量操作
什么是全量操作呢?就是上来就 hgetall、lrange(0,-1),smembers 等等这些一下就要获取所有数据的命令。有的时候因为集合里边的数据量比较大,一次性获取所有会导致 Redis 性能严重下降。
如果想要遍历所有数据,那么可以考虑使用 hscan、sscan 以及 zscan 这一类逐步分批扫描的命令,这样就能降低 Redis 的压力。当然,最好是能够从源头上避免这种情况,就是不要有 bigkey,将 bigkey 进行拆分。
7、不设置客户端连接数
为了确保 Redis 服务器的稳定性和性能,建议根据实际的应用场景和服务器资源情况,合理配置客户端连接数。
可以根据服务器的硬件资源和操作系统的限制,合理设置 maxclients 参数。设置完成之后,可以在高负载情况下测试 Redis 的性能,确保在实际使用中不会因为客户端连接数过多而导致性能下降或服务不稳定。
8、不设置密码
这应该没啥好说的,不设置密码会带来很多安全性问题。在其中设置密码通常通过配置文件中的 requirepass 指令来实现。例如:
requirepass yourpassword
甚至,在生产环境中,我们还应该考虑使用更高级的安全措施,例如:
1.使用 SSL/TLS 加密客户端和服务器之间的连接。
2.配置防火墙规则,只允许特定的 IP 地址访问 Redis 服务器。
3.定期更新和打补丁,以保护 Redis 服务器不受已知漏洞的影响。
为生产环境的 Redis 设置密码是确保数据安全和遵守最佳实践的重要步骤。
Redis(REmote DIctionary Server)是一个基于 C 语言开发的开源 NoSQL 数据库,与传统数据库不同的是,Redis 的数据是保存在内存中的(内存数据库,支持持久化),因此读写速度非常快,被广泛应用于分布式缓存方向。并且Redis存储的是 KV 键值对数据。
为了满足不同的业务场景,Redis 内置了多种数据类型实现(比如 String、Hash、Sorted Set、Bitmap、HyperLogLog、GEO);并且其还支持事务、持久化、Lua 脚本、多种开箱即用的集群方案(Redis Sentinel、Redis Cluster)。

Redis 数据类型概览
Redis 没有外部依赖,Linux 和 OS X 是其开发和测试最多的两个操作系统,官方推荐生产环境使用 Linux。
Redis 为什么这么快
其内部做了非常多的性能优化,比较重要的有下面 3 点:
1.基于内存,内存的访问速度是磁盘的上千倍;
2.基于 Reactor 模式设计开发了一套高效的事件处理模型,主要是单线程事件循环和 IO 多路复用;
3.内置了多种优化过后的数据类型/结构实现,性能非常高。
下面这张图片总结的挺不错的,出自 Why is Redis so fast?。

分布式缓存常见的技术选型方案有哪些
分布式缓存的话,比较老牌同时也是使用的比较多的还是 Memcached 和 Redis。不过现在基本没有看过还有项目使用 Memcached 来做缓存,都是直接用 Redis。
Memcached 是分布式缓存最开始兴起的那会比较常用的;后来随着 Redis 的发展,大家慢慢都转而使用更加强大的 Redis 了。
有一些大厂也开源了类似于 Redis 的分布式高性能 KV 存储数据库,例如,腾讯开源的 Tendis,其基于知名开源项目 RocksDB作为存储引擎,100% 兼容 Redis 协议和 Redis 4.0 所有数据模型。
不过从 Tendis 这个项目的 Github 提交记录可以看出,其开源版几乎已经没有被维护更新了,加上其关注度并不高,使用的公司也比较少。因此不建议使用 Tendis 来实现分布式缓存。
目前比较业界认可的 Redis 替代品还是下面这两个开源分布式缓存:
Dragonfly:一种针对现代应用程序负荷需求而构建的内存数据库,完全兼容 Redis 和 Memcached 的 API,迁移时无需修改任何代码,号称全世界最快的内存数据库。
KeyDB:Redis 的一个高性能分支,专注于多线程、内存效率和高吞吐量。
不过还是建议分布式缓存首选 Redis,毕竟经过这么多年的生产考研,生态也这么优秀,资料也很全面。说一下 Redis 和 Memcached 的区别和共同点
现在公司一般都是用 Redis 来实现缓存,而且 Redis 自身也越来越强大了!不过了解 Redis 和 Memcached 的区别和共同点,有助于在做相应的技术选型的时候能够做到有理有据!
共同点:
都是基于内存的数据库,一般都用来当做缓存使用。
都有过期策略。
两者的性能都非常高。
区别:
1、Redis 支持更丰富的数据类型(支持更复杂的应用场景)。它不仅仅支持简单的 k/v 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。Memcached 只支持最简单的 k/v 数据类型。
2、Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而 Memcached 把数据全部存在内存之中。
3、Redis 有灾难恢复机制。 因为可以把缓存中的数据持久化到磁盘上。
4、Redis 在服务器内存使用完之后,可以将不用的数据放到磁盘上。但是,Memcached 在服务器内存使用完之后,就会直接报异常。
5、Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 Redis 目前是原生支持 cluster 模式的。
6、Memcached 是多线程,非阻塞 IO 复用的网络模型;Redis 使用单线程的多路 IO 复用模型(Redis 6.0 针对网络数据的读写引入了多线程)。
7、Redis 支持发布订阅模型、Lua 脚本、事务等功能,而 Memcached 不支持。并且 Redis 支持更多的编程语言。
8、Memcached 过期数据的删除策略只用了惰性删除,而 Redis 同时使用了惰性删除与定期删除。
相信看了上面的对比之后,已经没有什么理由可以选择使用 Memcached 来作为自己项目的分布式缓存了。
为什么要用Redis作缓存
下面主要从“高性能”和“高并发”这两点来回答这个问题。
1、高性能
假如用户第一次访问数据库中的某些数据的话,这个过程是比较慢,毕竟是从硬盘中读取的。但是,如果说,用户访问的数据属于高频数据并且不会经常改变的话,那么我们就可以很放心地将该用户访问的数据存在缓存中。
2、高并发
一般像 MySQL 这类的数据库的 QPS 大概都在 1w 左右(4 核 8g),但是使用 Redis 缓存之后很容易达到 10w+,甚至最高能达到 30w+(就单机 Redis 的情况,Redis 集群的话会更高)。
QPS(Query Per Second):服务器每秒可以执行的查询次数;
由此可见,直接操作缓存能够承受的数据库请求数量是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。进而也就提高了系统整体的并发。
什么是 Redis Module?
Redis 从 4.0 版本开始,支持通过 Module 来扩展其功能以满足特殊的需求。这些 Module 以动态链接库(so 文件)的形式被加载到 Redis 中,这是一种非常灵活的动态扩展功能的实现方式,值得借鉴学习!大家都可以基于 Redis 去定制化开发自己的 Module,比如实现搜索引擎功能、自定义分布式锁和分布式限流。目前被 Redis 官方推荐的 Module 有:
RediSearch:用于实现搜索引擎的模块。
RedisJSON:用于处理 JSON 数据的模块。
RedisGraph:用于实现图形数据库的模块。
RedisTimeSeries:用于处理时间序列数据的模块。
RedisBloom:用于实现布隆过滤器的模块。
RedisAI:用于执行深度学习/机器学习模型并管理其数据的模块。
RedisCell:用于实现分布式限流的模块。
……
关于 Redis 模块的详细介绍,可以查看官方参考文档。
喜马拉雅Redis与Pika缓存使用规范
作者:喜马拉雅 董道光
宣言:缓存不是万金油,更不是垃圾桶!
缓存作为喜马拉雅至关重要的基础组件之一,每天承载着巨大的业务请求量。一旦缓存出现故障,对业务的影响将非常严重。因此,确保缓存服务的稳定和高效运行始终是我们的重要目标。下面是对喜马缓存历史故障复盘后总结的一套缓存使用规范,在此分享给大家,希望小伙伴们能在缓存选型和使用的过程中少踩坑。
1. 缓存选型
1.1 缓存类型介绍
喜马线上缓存类型主要有 4 种:
1. redis 主从模式:官方原版
2.codis-redis:豌豆荚开源,redis 集群解决方案
3.云数据库 redis:redis-cluster 容器化部署
4.xcache:基于 codis、pika、redis 自研的一套海量 KV 存储解决方案
1.2 缓存使用模式介绍
使用模式主要分为 2 种:
1.cache 模式:数据不需要持久化,实例恢复不需要加载数据,扩缩容不需要迁移数据
2.store 模式:数据需要持久化,实例恢复需要加载数据,扩缩容需要迁移数据
下面是对各种类型缓存做了简单对比:

2. 缓存使用军规
2.1 缓存类型使用规范
1)redis 集群模式首选云数据库 redis,海量 KV 存储首选 xcache
云数据库 redis 采用官方 redis cluster 模式,容器化部署,支持故障自动恢复和弹性伸缩,是当前 redis 集群的主推方案,但不支持数据持久化,如果必须要做数据持久化,并且对延时要求非常高,可以使用 codis redis。数据量非常大,并且对延时要求不是特别高,可以选择 xcache。
2)redis 不要当 db 使用,如果数据一定要做持久化,可以选择 xcache
redis 当 db 使用,故障恢复数据很慢,严重影响 SLA。并且如果主从全部挂掉,slave 机器无法恢复时,数据就会完全丢失。xcache 天然支持数据持久化。
3)不要使用客户端分片模式
客户端分片模式不具备高可用和弹性伸缩能力,建议使用真正的集群模式,如 codis-redis、云数据库 redis、xcache。
4)集群模式不支持 lua、redisson 客户端,如果业务必须使用,只能选择 redis 主从模式。
5)单节点容量阀值
redis 单节点容量不要超过 10GB,xcache 单节点容量不要超过 200GB;redis 单节点容量太大时,实例重启会比较慢,影响恢复时长。
2.2 键值设计规范
1)key 尽量保持简洁性、可读性、可管理性
在保证语义的前提下,控制 key 的长度;以业务名 (或数据库名) 为前缀 (防止 key 冲突),用冒号分隔,比如业务名:表名:id;不要包含特殊字符。
2)拒绝 bigkey,防止网卡流量过高、慢查询
string 类型控制在 10KB 以内,hash、list、set、zset 元素个数不要超过 5000。
3)避免热点 key
热 key 会导致数据倾斜,以及单节点压力过大。建议业务侧将热 key 打散。
4)控制 key 生命周期
缓存不是垃圾桶,最好对 key 都设置 ttl,并且将 key 的 ttl 打散,避免 key 集中过期。
2.3 命令使用规范
1)慎用全量操作命令
禁用 `keys *` 命令,尽量不使用 hgetall、smembers 等命令。在获取 key 下的多个元素时,使用相应的 scan 命令,一次获取少量元素,分多次获取,建议一次 scan 不要超过 200 个。
2)控制 mset、mget、hmset、hmget、*scan、*range 等命令单次操作元素数量,建议不要超过 200
3)控制 pipeline 中命令的数量,建议不要超过 100
4)redis 删除 key 时,不要用 del 命令,使用 unlink 命令
del 一个大 key 会直接导致 redis 卡住。使用 unlink 命令可以异步删除 key,不会对 redis 主线程产生影响,因此也不会影响业务流量。
5)set 和 expire 命令合并成 setex 命令,减少服务端写压力。
6)evalsha 代替 eval
redis-cluster 集群中使用 evalsha 代替 eval,减少网络 IO,同时也减小 redis 网络 IO 压力提高性能。
2.4 业务缓存架构规范
1)redis 不要使用逻辑 db,只使用默认 db 0
可以通过实例隔离,不同业务的数据保存到不同的实例中。(只有 redis 主从可以选择逻辑 db,集群模式默认都使用 db0)。
2)避免多业务复用同一缓存资源
不同业务的数据使用不同的集群,S 级应用不要和 B 级应用混用,过多业务复用同一资源要做拆分。业务尽量提供 rpc 接口给其它业务调用,而不是直接让其它业务访问数据源(如一个业务写,一个业务读)。
3)xcache 尽量使用 string 类型
xcache 支持 string,hash,ehash,list,set,zset 六种数据类型,ehash 数据类型是对 hash 数据类型的扩展,支持对 field 设置过期时间。xcache 中 string 类型是速度最快的,其他数据类型都是由 string 进行组合变换而实现,六种数据的性能如下:
string > hash > set > ehash > list > zset
建议:尽量使用 string 类型
4)减少 lua 脚本使用
集群模式对 lua 支持有限制,必须保证 lua 中操作的 key 被 sharding 到同一个节点。所以尽量减少对 lua 的使用。
5)lua 脚本中不跑复杂逻辑
复杂逻辑放在业务代码中,而不是 lua 脚本中。
6)采用高效序列化方法和压缩方法
为了节省内存,如果 value 较大时,可以使用压缩工具(如 snappy 或 gzip),把数据压缩后再写入 redis。
7)避免批量任务、定时任务、周期任务流量太大影响在线业务
批量任务、定时任务、周期任务业务上要做限速。
8)业务变更,存储流量模型变化要先评估
业务模型变化,QPS、容量增加,O (N) 命令增多等都要先评估当前缓存是否抗的住,做到灰度上线,持续观察(尤其是流量高峰期)。
9)不用的资源尽早申请回收
休眠资源回收不仅可以降低业务的存储成本,还可以把资源分配给真正需要的业务,可谓是双赢。
3. 优化参考
实施流量压缩方案、清理无效数据、治理实例 TTL、下线无用实例等优化措施,涉及流量复制、流量放大、数据迁移、数据在线压缩与解压缩、数据定向清理与定向指定 TTL、扫描分析 Key 最后访问时间等工具辅助方案落地。
1、清理未使用的实例
有的业务下线了但实例还在,需要清理这类实例。这个是最容易实现的,最快能优化的,通过采集 Redis Metrics 数据,筛出长期 QPS 非常低的实例(集群版本 Redis, 自身也会有 ping 等保活访问),观测连接数据等,和业务确认并释放。
2、实例降配:提高内存使用率
各种因素,导致实际使用的内存,和申请的内存差别较大,导致使用率上不去,存在内存浪费。比如:
业务容量预估偏差导致的内存长期使用率偏低
业务进入稳定期,内存不在快速增长,内存使用率较稳定
这些场景需要通过降配,将使用率至少稳定在 70% 左右。降配时,需要注意如下:
集群降配到主从,注意业务端的链接模式是否兼容
大集群降配到小集群,注意是否有大 key 限制
大集群降配到小集群,注意数据倾斜问题导致小集群节点塞满了
大集群降配到小集群,注意节点数的变化,比如 128 节点降配到 32 节点,性能落差会非常大。
除了内存使用率,降配时还需要注意带宽的使用情况,
降配时,尽量在同等容量规格的情况下,选择节点数最多的规格,节点数越多性能越好。比如同样是 256GB 的,优先选择 128 节点 2GB 的集群,不要选择 32 节点 * 8GB 的集群。
降配时,会存在连接闪断抖动,尽量在业务低峰期进行。
3、使用场景打标,允许部分场景内存用满
使用 Redis 的情形可分类为【被动缓存】、【非被动缓存】两类场景。
【被动缓存】:典型的缓存场景,用来挡在 MySQL 前面抗流量(先请求 Redis 拿数据,没拿到则到 MySQL 里取数据,设置到 Redis),Redis 内存用满时也不用扩容,设置好驱逐策略即可。
【非被动缓存】:搜广推场景的特征数据,Redis 里的数据是实时流、离线等业务主动写入的。如果内存到了 90% 告警线,需要及时扩容,避免重要数据被驱逐
通过合理的区分不同 Redis 实例的使用场景,制定不一样的告警策略,允许部分场景 Redis 使用率 100%,可进一步提高整个 Redis 的内存使用率。实施时需要注意如下:
被标记为【被动缓存】的实例,需要明确所有的 key 都设置了 TTL ,明确允许所有的 key 都允许被驱逐。否则会导致内存用满,然后写入被拒的情况。
被标记为【被动缓存】的实例,在主从架构中,可关闭主服务的 aof(aof 关闭涉及到 config rewrite 会阻塞主进程,会对线上集群产生影响,应尽量在业务低峰期操作),降低数据驱逐时的性能影响,提高性能。
4、合理设置 TTL
使用 Redis 时,99% 的场景 Key 是可过期删除的。只不过,不同的场景对 TTL 的要求是不一样的,这个需要业务自行判断。但是 infra 可以把大实例的 TTL 比例全部捞出来从大到小依次过一遍。
有的实例 32G 没有设置 TTL ,实际活跃实际只有 32G 不到,通过设置合理的 TTL ,可以优化 50% 的内存。
有的实例 TTL 设置了一年,实际活跃数据只有半年,或者一个月
以上都可以通过设置合理的 TTL,来优化内存使用。实施时需要注意如下:
实施前需要采集 Redis Metrics 数据,筛出内存规格大,未设置 TTL key 占比高的实例。
大部分场景其实业务也不知道合理的 TTL 是多少。所以需要准备好 Key 的访问时间(最后一次访问)分布情况,这个需要 scan 分析,后文会提到这个工具。提供给业务做 TTL 决策。
有了预期的 TTL 后,需要将所有的数据都刷一遍。所以需要一个刷 TTL 的运维工具脚本,同时可以指定清理最后一次访问距今时间的数据。
5、清理历史数据
部分业务把 Redis 当持久化存储,但是中间数据结构发生过变化,导致历史无用数据占用内存空间。这个场景和 5、合理设置 TTL 有点类似,同样需要:
准备好 Key 的访问时间(最后一次访问)分布情况,提供给业务做数据清理决策。
有了预期的清理逻辑后,需要一个清理 Key 的运维工具脚本,功能包含【指定 key 前缀清理】、【指定清理最后一次访问距今时间的数据 Key】。
6、改进 kv 结构
部分业务把整个大的 json 对象一股脑的存到 Redis ,其实部分字段用不着,可以裁剪 value 的大小,减少内存使用。
部分场景,比如判断用户设备是否是新设备,采用 Bloomfilter 相比 String,相同数据规模,可以节省 90% 以上的内存。
7、定期 scan, 释放已过期的内存
因为 Redis 已过期 key 的清理策略,是惰性删除的(已经过期的 key ,只有被访问过或者 hz 扫描到才会被删除),所以通过定期使用 SCAN 命令扫描键空间并手动删除已过期的键,可以更精细地管理 Redis 内存,提高系统的稳定性和资源利用效率。实施时需要注意:选择在业务低峰期进行,控制好 SCAN 的速率,尽量减少对线上业务的影响。
8、降低可用性
在 dev、qa 环境中,可通过如下措施来进一步降低成本:
合并小实例,部分实例已经是最小规格,但是内存使用率只有不到 10%,这种情况下,可以通过小实例合并来缩减成本
在 dev、qa 等对可用性要求不高的环境里,可通过对集群、主备版本,降配到单实例规格降低成本。
9、压缩 value
选择合适的压缩算法,对 value 进行压缩后存储。部分场景的压缩率可达 50%~80%,意味着部分实例至少可优化 50% 左右的内存。因为这个方案实施比较复杂,所以尽量挑选 100GB 以上的实例进行优化,性价比较高。适合压缩的特征如下:
value 大(100b 以上),字符重复度高
有3个主流的压缩算法,gzip 、zstd、snappy。测试下来 ,不同的压缩算法特点如下:
gzip 、zstd: 这两个压缩和解压缩表现都不错,性能比较均衡。在不同的 value 特征的压缩 & 解压缩性能表现差异不大
snappy:压缩比较耗时,但是解压缩非常快。
对 852k 的一个 user_profile 数据做了一个测试,(不同大小的数据性能差异较大,最终应该以线上数据流量的测试结果为准) 测试方法:运行 100 次取均值
snappy
压缩耗时:122722us
压缩率:22.60%
解压耗时:49us
gzip
压缩耗时:39821us
压缩率:15.79%
解压耗时:3521us
zstd
压缩耗时:6953us
压缩率:17.08%
解压耗时:3153us
最后 snappy 就直接否了,因为压缩的资延时不符合预期;然后不同的实例都验证下 gzip、zstd 哪个性能好就选择哪个。具体实施时需要注意如下:
1.准备好 Redis 流量复制的工具,复制线上流量进行 zstd、gzip 的压缩、解压缩性能测试,明确压缩率、压缩延时和解压缩延时数据。
2.定制 Redis 访问客户端,无缝兼容各种指令的 gzip 、zstd 压缩数据,做到应用端不用改代码,只需要升级客户端版本就可以完成压缩、解压缩兼容。
3.研发存量数据全量压缩的运维工具,这个工具支持指定压缩算法、支持指定 Key 前缀压缩、支持解压缩等。
4.注意开启压缩后,对应用 CPU 等资源消耗的的影响,读取延时普遍会增加 1~2ms 左右。
5.刷线上存量的数据压缩前,确保应用都更新到兼容压缩的 Redis 访问客户端了,然后对部分 key 灰度压测,观测线上情况,没有问题后在全量刷。发现问题后及时解压缩。
10、迁移到兼容 Redis 协议的磁盘存储项目
早期本着性能优先的原则,所有的 Redis 实例都是【内存型】。随着数据规模增大,内存资源占用会随之递增,Redis 存储成本大幅攀升。另一方面,随着业务的发展,当业务进入发展后期,数据量已经形成一定规模,而数据的访问频度则慢慢降下来,资源使用率普遍偏低。针对这类问题,可重新从性能、和成本综合评估业务更适合【内存型】、【磁盘型】的 Redis 实例。
内存型
优点:性能好(p99 延时很稳定)、扩展性好、支持水平伸缩
缺点:成本高
磁盘型
基于 RocksDB 实现的磁盘存储、兼容 Redis 协议的产品,社区里也有 pika、kvrocks 这类项目。
优点:成本低,是内存型的 16%。有容量起点,相比内存型,至少存储 64GB 以上才有性价比。
缺点:性能一般(p99 延时存在波动,突刺效应明显),是内存型的 70% 性能。且只支持垂直扩容,没法水平伸缩。
这个优化措施涉及到数据的迁移,且需要兼顾业务稳定性。所以实施起来比【压缩 Value】还要复杂,主要注意点如下:
1.如何筛选迁移到【磁盘型】的 Redis 实例?写请求低于 10k/s ,读请求低于 100k/s, 对 p99 时延要求不敏感,比如可以接受 avg 大于 0.5ms ,p99 5ms 的场景,且存储容量非常大 100GB 以上 ,而且预期存储容量会进一步增长。
2.采集好【磁盘型】的 Metrics ,做好监控观测。阿里云只给了基础的 Metrics,底层的数据指标,比如 RocksDB 层的、以及指令级的延时(对后面判断指令性能问题非常有帮助)、QPS 等都需要通过 info 指令拿到信息后自己解析采集。
3.准备好 Redis 流量复制工具,复制线上流量到【磁盘型】Redis 目标实例,对流量进行等比,加倍回放,对每个迁移的实例针对性的进行性能压测验证。确保覆盖每个指令的性能问题、兼容问题。
4.对【磁盘型】实例做好容量规划,QPS 增长评估。
5.使用 DTS 进行数据迁移时,确保原实例内存至少有 20% 的冗余,否则需要先扩容原实例在迁移。因为 DTS 是基于【Redis 主从复制这套逻辑】来进行同步的,同步时,缓冲区需要占用内存。
6.如果原实例的写入流量较大,DTS 迁移前,最好先调整下【 client-output-buffer-limit replica】、【repl-backlog-size 】、【DTS 收到 Master 的 RDB 后,立马回复 ACK 的开关】这些参数,避免同步反复失败。
Redis操作时几个低级错误
1、FLUSHALL 和 FLUSHDB
这两个命令会分别清空所有数据库或当前数据库中的所有数据。由于它们会删除大量数据,数据量大的时候会对性能产生明显影响;并且如果使用不当,可能会导致数据丢失。为了避免误操作,可以考虑在配置文件中禁用或重命名这些命令。
2、KEYS
这个命令用于查找所有匹配给定模式的键。这个命令会扫描整个键空间,可能会导致性能问题,因为它会锁定数据库直到搜索完成。一个比较好的替代是使用 SCAN 命令,它提供了一种逐步迭代 Redis 中的键的方式,而不会阻塞服务器。
3、CONFIG
这个命令允许客户端动态地修改 Redis 配置。出于安全考虑,应该避免使用此命令,因为这可能会被用来更改重要的配置,从而影响服务器的稳定性和安全性。Redis 配置建议最好都在 redis.conf 中直接配置好再启动,这是最佳实践。
4、MONITOR
这个命令用来实时监控 Redis 服务器接收到的命令。在高负载的情况下使用它可能会导致性能问题,因为它会增加 Redis 的输出缓冲区的内存使用,命令多的时候可能会造成缓冲区溢出。
5、直接删除 BIGKEY
当你发现 Redis 中存在 BIGKEY 的时候,二话不说就想用 DEL 将其干掉。在 Redis 中,直接删除 bigkey 会对性能产生负面影响。因为 Redis 是单线程处理请求的,删除 bigkey 会占用较长时间,从而阻塞其他请求的处理。
那么如果想要删除 bigkey 该怎么处理呢?
1.分批删除:可以尝试分批删除 bigkey 中的元素,例如使用 LREM 命令从列表中移除元素,或者使用 ZREM 命令从有序集合中移除元素。这样可以减少一次性删除大量元素对性能的影响。
2.使用 UNLINK 命令:在 Redis4.0 及以上版本中,可以使用 UNLINK 命令来异步删除 key。这个命令会将删除操作放入后台处理,不会立即释放内存,从而减少了对主线程的阻塞。
3.使用 SCAN 命令:如果需要删除多个 bigkey,可以使用 SCAN 命令配合 DEL 命令来分批次删除,以减少对服务器性能的影响。
4.使用 lazy-free 机制:在 Redis4.0 及以上版本中,可以开启 lazy-free 机制,使得内存释放操作在后台线程中进行,减少对主线程的影响。
5.避免创建 bigkey:最好的方法是避免创建 bigkey。设计应用程序时,应该尽量将数据分割成更小的块,这样可以提高性能并减少删除操作的复杂性。
6、动辄全量操作
什么是全量操作呢?就是上来就 hgetall、lrange(0,-1),smembers 等等这些一下就要获取所有数据的命令。有的时候因为集合里边的数据量比较大,一次性获取所有会导致 Redis 性能严重下降。
如果想要遍历所有数据,那么可以考虑使用 hscan、sscan 以及 zscan 这一类逐步分批扫描的命令,这样就能降低 Redis 的压力。当然,最好是能够从源头上避免这种情况,就是不要有 bigkey,将 bigkey 进行拆分。
7、不设置客户端连接数
为了确保 Redis 服务器的稳定性和性能,建议根据实际的应用场景和服务器资源情况,合理配置客户端连接数。
可以根据服务器的硬件资源和操作系统的限制,合理设置 maxclients 参数。设置完成之后,可以在高负载情况下测试 Redis 的性能,确保在实际使用中不会因为客户端连接数过多而导致性能下降或服务不稳定。
8、不设置密码
这应该没啥好说的,不设置密码会带来很多安全性问题。在其中设置密码通常通过配置文件中的 requirepass 指令来实现。例如:
requirepass yourpassword
甚至,在生产环境中,我们还应该考虑使用更高级的安全措施,例如:
1.使用 SSL/TLS 加密客户端和服务器之间的连接。
2.配置防火墙规则,只允许特定的 IP 地址访问 Redis 服务器。
3.定期更新和打补丁,以保护 Redis 服务器不受已知漏洞的影响。
为生产环境的 Redis 设置密码是确保数据安全和遵守最佳实践的重要步骤。