产品战略专家梁宁确认出席AICon北京站,分享AI时代下的商业逻辑与产品需求 了解详情
写点什么

Redis 开发设计规范及案例分析

  • 2019-10-21
  • 本文字数:3290 字

    阅读完需:约 11 分钟

Redis开发设计规范及案例分析

redis 不是垃圾桶也不是 SUPER MAN,能力和资源都有限,不合理的使用会降低它的健康度,严重时甚至会引起 redis 抖动、阻塞等进而导致服务不可用,每一个使用 redis 的开发人员都应当掌握规范的开发和使用方法。本文整理出 redis 开发过程中七个较常出现的使用不合理的场景,并辅以案例进行分析说明。

01 合理使用集合类

案例

某活动需求,每天 10 点对昨天参加某活动的用户进行推送提醒。开发人员使用 redis 存储每天参加活动的用户,通过 ZRANGEBYSCORE 命令获取目标用户进行提醒,提醒完后使用 ZREMRANGEBYSCORE 命令从 redis 中清除这批用户。某一天 ZRANGEBYSCORE、ZREMRANGEBYSCORE 均出现了慢日志报警,排查发现这一天参加该活动的用户约有 5 万。

分析

案例中使用了 redis 的 sortedset 来储存用户信息,其中 value 是用户的账号、score 是用户参加活动的时间,由于 ZRANGEBYSCORE 和 ZREMRANGEBYSCORE 命令的时间复杂度是 O(log(N) + M),其中 M 是操作的元素个数,N 是集合元素总数,本例中当用户数量为 5 万时出现慢日志。可以通过缩小每次查询的集合数量,可以将一天分成多段,分批次查询,比如把查 24 小时范围的用户改为查 4 小时范围的用户,分别查 6 次处理即可。

Q

如果用户参加活动的时间很集中,在某一个时间段(比如晚 18 点到 22 点)查出来的数量还是特别多怎么办?

A

可以把粒度分得更细一些比如 1 小时或者 30 分钟,如果确定用户参加活动集中在某个时间点,可以考虑使用 ZSCAN 遍历操作并删除。另外,对于目标时间范围有确定的首尾元素时,还可以通过 ZRANK 命令查出元素的位置,通过 ZRANGE 以及 ZREMRANGEBYRANK 来进行查询和删除操作,这样每次操作可以控制操作数量,有效避免慢日志。

小结

使用 sortedset、set、list、hash 等集合类的 O(N)操作时要评估当前元素个数的规模以及将来的增长规模,对于短期就可能变为大集合的 key,要预估 O(N)操作的元素数量,避免全量操作,可以使用 HSCAN、SSCAN、ZSCAN 进行渐进操作。集合元素数量过大在使用过程中会影响 redis 的实际性能,元素个数建议尽量不要超过 5000,元素数量过大可考虑拆分成多个 key 进行处理。

02 合理设置过期时间

案例 1

某投票功能,用于统计今日环比昨日的增长数量,开发人员使用 redis 存储每天的投票数,key 设计为 vote_count_{date},其中{date}为当天的日期,由于没有设置过期时间,一年以后产生了 360 多个 key,实际在用的 key 始终只有 2 个。

分析

该案例中,每个生成的 key 在 2 天以后都不会再使用了,可将 key 加上过期时间。

案例 2

某统计功能,用户会不定期的导入一批数据进 redis,每一批数据需要在 30 分钟后、1 天后、3 天后、7 天后进行计算统计,统计结果发给用户。开发人员使用 redis 的同一个 sortedset 存储这些导入的数据,每天定时任务执行计算任务。由于没有清理,导致大量结束计算任务的废弃数据残留 redis。

分析

该案例中,每一批数据都有相应的生命周期,在导入的第 7 天执行完最后一次计算任务生命周期结束,由于集合里的元素不能单独设置过期时间,可在代码逻辑中对最后一次使用这批数据后进行清理操作。

小结

如果 key 没有设置超时时间,会导致一直占用内存。对于可以预估使用生命周期的 key 应当设置合理的过期时间或在最后一次操作时进行清理,避免垃圾数据残留 redis。

03 合理利用批操作命令

案例

某运营需求,需要给用户生成短链,短链由短链前缀+短码组成,根据短码找到用户对应的手机号,开发人员使用 redis hash 结构存储短码到手机号的映射。接口每次会导入 5 万个手机号。

分析

下面是开发人员的三种操作 redis 方案的伪代码


方案 1:直接使用 redis 的 HSET 逐个设置


for(50000;)HSET(key,短码,手机号)
复制代码


结果:失败。redis ops 飙升,同时接口响应超时


方案 2:改用 redis 的 HMSET 一次将所有元素设置到 hash 中


map<短码,手机号> 50000个元素HMSET(key,map)
复制代码


结果:失败。出现 redis 慢日志


方案 3:依然使用 HMSET,只是每次设置 500 个,循环 100 次


map<短码,手机号> 500个元素for(100;)HMSET(key,map)
复制代码


结果:成功


对于大量频繁的 hset 操作可以使用 HMSET 替代减少 redis 操作次数同时提升处理速度,但是要考虑单次请求操作的数量,避免慢日志。

小结

在 redis 使用过程中,要正视网络往返时间,合理利用批量操作命令,减少通讯时延和 redis 访问频次。redis 为了减少大量小数据 CMD 操作的网络通讯时间开销 RTT (Round Trip Time),支持多种批操作技术:


MSET/HMSET 等都支持一次输入多个 key,LPUSH/RPUSH/SADD 等命令都支持一次输入多个 value,也要注意每次操作数量不要过多,建议控制在 500 个以内;


PipeLining 模式 可以一次输入多个指令。redis 提供一个 pipeline 的管道操作模式,将多个指令汇总到队列中批量执行,可以减少 tcp 交互产生的时间,一般情况下能够有 10%~30%不等的性能提升;


更快的是 Lua Script 模式,还可以包含逻辑。redis 内嵌了 lua 解析器,可以执行 lua 脚本,脚本可以通过 eval 等命令直接执行,也可以使用 script load 等方式上传到服务器端的 script cache 中重复使用。

04 减少不必要的请求

案例

某业务系统,当用户进入某个页面时会同时请求多个接口,每个接口都会校验用户状态是否有效,用户状态存在 redis 里并设置有过期时间,对于 key 未过期但是过期时间大于指定阈值的,需要重新设置有效时间,否则需要使用 del 命令删除掉。但是部分 key 由于过期其实已经不存在了,所以出现部分无效 del 命令。用户越多,就会有越多的无效命令。

分析

ttl 命令对于 key 不存在的情况会返回-2,若 key 不存在则不需要再调用 del 命令,可减少无效请求。

小结

redis 的所有请求对于不存在的 key 都会有输出返回,合理利用返回值处理,避免不必要的请求,提升业务吞吐量。

05 避免 value 设置过大

案例

某开发人员将一个商品集合信息序列化后用 redis 的字符串类型存储,使用的时候再反序列化成对象列表使用,大小超过 1MB,在网络传输的时候由于数据比较大会触发拆包,会降低 redis 的吞吐量。

分析

数量比较多时可以考虑改用 hash 结构存储,每一个 field 是商品 id,value 是该商品对象,如果数量较大可使用 hscan 获取。

小结

String 类型尽量控制在 10KB 以内。虽然 redis 对单个 key 可以缓存的对象长度能够支持的很大,但是实际使用场合一定要合理拆分过大的缓存项,1k 基本是 redis 性能的一个拐点。当缓存项超过 10k、100k、1m 性能下降会特别明显。关于吞吐量与数据大小的关系可见下面官方网站提供的示意图。



吞吐量与数据大小的关系


在局域网环境下只要传输的包不超过一个 MTU(以太网下大约 1500 bytes),那么对于 10、100、1000 bytes 不同包大小的处理吞吐能力实际结果差不多。

06 设计规范的 key 名

可读性

以业务名为前缀,用冒号分隔,可使用业务名:子业务名:id 的结构命名,子业务下多单词可再用下划线分隔。


举例:活动系统-人拉人红包活动-id,可命名为 ACTIVITY:INVITE_REDPACKET:001

简洁性

保证语义的前提下,控制 key 的长度,当 key 较多时,内存占用也不容忽视。

不包含转义字符

不包含空格、换行、单双引号以及其他转义字符。

07 留心禁用命令

keys、monitor、flushall、flushdb 应当通过 redis 的 rename 机制禁掉命令,若没有禁用,开发人员要谨慎使用。其中 flushall、flushdb 会清空 redis 数据;keys 命令可能会引起慢日志;monitor 命令在开启的情况下会降低 redis 的吞吐量,根据压测结果大概会降低 redis50%的吞吐量,越多客户端开启该命令,吞吐量下降会越多。


keys 和 monitor 在一些必要的情况下还是有助于排查线上问题的,建议可在重命名后在必要情况下由 redis 相关负责人员在 redis 备机使用,monitor 命令可借助 redis-faina 等脚本工具进行辅助分析,能更快排查线上 ops 飙升等问题。

总结

本文整理出的几点 redis 开发规范主要是涉及 redis 客户端的使用部分,每个开发人员在使用 redis 开发过程中几乎都会涉及到上述提到的几个问题,需要多多留心,提高代码质量,提升 redis 的健康度。


本文转载自公众号中间件小哥(ID:huawei_kevin)。


原文链接:


https://mp.weixin.qq.com/s/gw1X34vtiwRcEYgLbWp23w


2019-10-21 11:191138

评论

发布
暂无评论
发现更多内容

mac磁盘诊断和监测工具DriveDx for mac

Mac相关知识分享

加强科技平台企业赋能 加快发展新质生产力

不在线第一只蜗牛

低代码 数字化

【论文速读】| RED QUEEN: 保护大语言模型免受隐蔽多轮越狱攻击

云起无垠

python 爬虫如何爬取动态生成的网页内容

快乐非自愿限量之名

Python 爬虫

有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?

王磊

VMware ESXi 8.0U3 Dell (戴尔) 定制版更新 OEM BIOS 2.7 支持 Windows Server 2025

sysin

macos esxi OEM unlocker dell

如何在鲲鹏平台上快速上手应用开发?鲲鹏DevKit给你答案

华为云开发者联盟

性能调优 鲲鹏 鲲鹏DevKit

低成本打造内容丰富的体育直播平台?看看这两个策略

软件开发-梦幻运营部

Js内建对象

EquatorCoco

JavaScript vue.js 前端

VMware ESXi 8.0U3 xFusion (超聚变) 定制版更新 OEM BIOS 2.7 支持 Windows Server 2025

sysin

macos esxi OEM Xfusion

RUM最佳实践:内网IP地址映射地图地理位置场景

观测云

RUM

遇到慢查询怎么办?一文解读MySQL 8.0查询分析工具

快乐非自愿限量之名

MySQL 数据库

Autodesk AutoCAD 2020 for mac(cad2020)激活版

Mac相关知识分享

ElevenLabs X-to-Voice:社交账号自动生成能说话的个人页面;OpenAI 正式推出 ChatGPT 搜索

声网

HarmonyOS 5.0应用开发——音频播放组件的封装

高心星

鸿蒙 HarmonyOS 鸿蒙5.0 HarmonyOS NEXT

企业选择云桌面系统的主要原因是什么?

青椒云云电脑

云桌面 云桌面系统

确保数据安全!使用Spring Boot 实现强大的API输入验证

江南一点雨

青椒云云桌面针对中小企业上云的服务怎么样?

青椒云云电脑

云桌面 云电脑 云桌面厂商

云桌面解决方案-青椒云

青椒云云电脑

云桌面 云桌面厂家 云桌面解决方案

华为云开源项目Sermant正式成为CNCF官方项目

华为云开发者联盟

微服务 cncf #云原生 #开源 sermant

运营TikTok需要什么网络环境

Ogcloud

云手机 海外云手机 tiktok云手机 tiktok运营 tiktok运营干货

VMware Aria Automation 8.18 发布,新增功能概览

sysin

vmware automation aria

一文彻底弄懂Java的IO操作

不在线第一只蜗牛

Java Python io

Astute Graphics for Mac(全系列ai插件合集)

Mac相关知识分享

Databend 产品月报(2024年10月)

Databend

高并发编程/一张图精通CompletableFuture整体执行流程与设计(高手篇)

肖哥弹架构

Java 并发编程 高并发

MacBook 触控板窗口管理软件Swish for Mac

Mac相关知识分享

主流电商平台售后API接口代码【详细】

快递鸟

API 接口

云电脑与远程控制软件的区别

青椒云云电脑

云桌面 云电脑 云桌面厂家

ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力

ClkLog

开源 sdk HarmonyOS 用户画像

游戏显卡VS专业显卡:两者有什么区别?

Finovy Cloud

显卡

Redis开发设计规范及案例分析_文化 & 方法_张家江_InfoQ精选文章