2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

5 个步骤构建优质 Redis 模块

  • 2020-03-01
  • 本文字数:2515 字

    阅读完需:约 8 分钟

5个步骤构建优质Redis模块

编写 Redis 模块时,请牢记以下五个步骤。虽然这份清单并不详尽,但是如果你还没有太多的模块构建经验,我还是能为你提供一个很好的入门方法的。

1、确定一个有吸引力的模块用例

Redis 有大量的工具可以让你构建所需的解决方案。一个例子就是锁。通过将 SET 与 NX 选项一起使用,你可以创建一个锁的 key,并将其与 EXPIRE 结合使用,即可得到一个锁租约。这在解决协调一致问题时非常有用。当内置命令还不够用时,你还可以使用 Lua 脚本,这些脚本为复合操作添加了完全的可编程性,然后由 Redis 原子地执行这些操作。


与 Lua 相比,模块在访问低层次 API 的能力方面,具有更大的灵活性和更快的速度,但是它们在维护和分发方面更具挑战性。仅在 Lua 不能完全适用你的用例时才使用模块。


模块可以添加新的命令


模块可以使用 C 语言向 Redis 添加新的命令(确切地说,你也可以使用 Rust,Zig 或任何 C-ABI 兼容语言)。你在功能上做什么取决于你自己。可以从实现与现有命令相似但可以有更多功能的命令开始。SETNE(由用户在此 GitHub Pull Request 中首次提到)就是一个示例。SETNE 的行为与 SET 完全相同,但是当新值等于当前值时,它不会修改键值,从而避免产生假的键空间通知。通常,要进行一些练习,可以考虑对现有命令添加一些附加功能,以帮助处理特定的用例。


大多数这些小的附加功能最好使用 Lua 脚本来实现,如果你刚开始想不出有吸引力的模块,这将是一种好方式。留给读者的几个练习:SETEQ,HINCRDATEBY。


模块可以添加新的数据类型


模块向 Redis 添加功能的最有效方法是添加新的数据类型。Redis 非常注重数据结构及其相关算法和属性的设计。尽管你可能不知道 Set 数据类型具体是怎么实现的,但是你肯定知道 SISMEMBER 命令执行很快,却与 Set 大小无关(例如,它具有亚线性渐近复杂度)。| 有关 BigO /渐近复杂度和 Redis 数据类型的重要性的介绍,请查看 Rob Conery 的演讲:https://www.youtube.com/watch?v=znYgNXN98Ag


这是我们自己的模块背后的基础:


•RediSearch 是基于倒排索引的全文本搜索模块。


•RedisGraph 是基于稀疏矩阵的图形模块。


•RedisTimeSeries 与 Redis Streams 类似,但针对数字序列进行了优化。


•RedisBloom 提供了一些不同的概率数据结构。


•RedisAI 运行 Tensorflow 深度学习图(以及其他一些类型)。


这些是很重要的模块,但并不是每个引入新数据类型的模块都必须如此复杂。有许多更简单的数据类型可用作模块。一个基本的示例就是 Redis 中已经存在的数据类型的不同实现,例如,使用 ArrayList 实现 List。

2、完善你的 API

不要忘记模块命令的错误用法与正确用法一样重要。Redis 用户喜欢手动调试命令以获得更好的理解,并且会输入一些错误的参数。你的 API 应该易于使用且难以滥用,但是当不可避免的情况出现时,请确保输出的错误信息是有意义的。


查看 Redis 的标准命令是如何工作的,然后看看执行你自己的命令得到的结果是否符合相应的假设。这将减少使用命令所需的心理负担。一个例子是,在 Redis 中,当调用一个不存在的键时,大多数命令都有合理的行为:INCR 会假定缺少的键值为 0,因此它会将其设置为 1,SADD 会假定缺少的键是空键,依此类推。

3、做一个好公民

模块需要可以与 Redis 生态进行交互。确保阅读文档以了解如何正确获取详细信息,尤其是当你的模块实现了新的数据类型时。这是两个最重要的方面。


命令标志


声明新的命令时,必须指定一些标志来告诉 Redis 调用命令时将要执行的操作。它是要读取数据还是要写入数据?是分配内存还是只是修改现有的数据?确保正确填写这些选项。例如,在内存不足(OOM)的情况下,deny-oom 是一个重要标志,它将告诉 Redis 拒绝访问分配内存的命令,否则整个进程将被 OOM 杀掉!即使是只读标志也很重要。新的客户端缓存功能将使用它来决定是否启用对给定 key 的跟踪。


命令复制


当 Redis 是主从模式时,主服务器必须知道应该将哪些命令发送给从服务器。并非每个命令都应复制,某些命令可能仅在特定条件下才需要复制。例如,我上面提到的 SETNE 命令,该命令仅在新值与当前值不同时才设置 key 和 value(否则它什么也不做)。在这种情况下,仅当命令有效地对 key 进行更改时,才应复制该命令。如果没有执行任何写操作,就不用让每个从服务器都执行该命令。

4、撰写出色的文档

如果你的模块都没有人知道如何使用,那么无论它多么有用都没有意义。因此完善 API 文档会有很大帮助,至少你首先得说服潜在用户该模块是值得尝试的。一个好的模块应该具有好的文档,这些文档可以明确该模块的总体目标并列出每个命令的详细信息。


如果看一下 redis.io,你就会发现每个命令都列出了其相对的 BigO 复杂性,并在命令具有特别大或小的常量或有明显边界情况时提供了一些额外的说明。尝试模仿这样的格式,尤其是在命令示例的语法方面。请注意,每个示例都是用小写字母命名占位符,大写字母表示关键字,方括号之间是可选值。查看 SET 的文档https://redis.io/commands/set 以查看此示例。


最重要的是:力求简单


始终牢记,Redis 背后的第一个设计原则是简单。这并不是说你的模块就只有这一种选择,偶尔还是可以为了其他好处而牺牲这种简单性(模块的存在正是为了让 Redis 用户体验),但要时刻注意你所放弃的东西。


一般而言,当你为了方便使用而牺牲了简单性时,也隐含地限制了用户使用模块的方式。在 Redis 中,大多数程序并不是单独使用某个命令,而是将不同的命令组合在一起使用。更小,更清晰,更简单的命令会更易于组合,因此在整体方案中会产生更好的效果。因此,我建议在进行这种权衡之前,通过适当地应用上述技术来提高易用性。


另一个潜在的权衡取舍可能是执行效率。这可能值得探索,也是 Redis 偶尔做的一个。某些内置数据类型具有两种内部的优化方式:一种是在数据类型中只有几个元素时进行优化,另一种针对 key 增长超过某个阈值时进行优化。两种方式(加上在两种方式之间进行切换的机制)肯定比只有一种方式更为复杂,但是这样做是值得的。因为增加的复杂性不会显示在用户界面中,无论使用哪种内部优化的方式,用户都将以相同的方式与数据类型进行交互。


本文转载自 中间件小哥 公众号。


原文链接:https://mp.weixin.qq.com/s/x6WTI25xBeFhdqSv65ph0Q


2020-03-01 21:421780

评论

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

物联网场景中灵活实施对设备的控制管理

亚马逊云科技 (Amazon Web Services)

2021年12月券商App行情刷新及交易体验评测报告

博睿数据

首届LoongArch生态创新大会成功召开,筑巢引凤共建信息产业命运共同体

OpenAnolis小助手

开源 芯片 白皮书

工业生产中的“主动刹车”,是怎么实现的?

脑极体

腾讯云 AI 视觉产品基于流计算 Oceanus(Flink)的计费数据去重尝试

腾讯云大数据

AI flink window

阿里云手机正式公测,定义手机全新接入方式

阿里云弹性计算

阿里云 弹性云手机

吐槽一下网站

你?

失去了SDK,云计算将会怎样?

亚马逊云科技 (Amazon Web Services)

计算

透析阿里云视频云「低代码音视频工厂」之能量引擎——vPaaS视频原生应用开发平台

阿里云CloudImagine

云计算 阿里云 音视频 低代买

恒源云(GPUSHARE)_语音识别与语义处理领域之低资源机器翻译综述

恒源云

机器翻译 语音识别

专注于最有价值的事情!——亚马逊云科技首席科学家工作心得分享

亚马逊云科技 (Amazon Web Services)

Date

模块9作业

Asha

VuePress 博客优化之开启 Gzip 压缩

冴羽

nginx 前端 后端 博客 vuepress

【网络安全】手把手给大家演练红队渗透项目

H

网络安全 渗透测试·

openGauss数据库源码解析系列文章——存储引擎源码解析(五)

低代码实现探索(十六)业务勾连复杂验证器

零道云-混合式低代码平台

在线常用crontab表达式大全验证解析

入门小站

工具

边缘网络 eBPF 超能力:eBPF map 原理与性能解析

火山引擎边缘云

Linux之df命令

入门小站

Linux

转换匹配患者记录,看Amazon Lake Formation FindMatches显神通!

亚马逊云科技 (Amazon Web Services)

analytics

腾讯云原生实时数仓建设实践

腾讯云大数据

flink window 流计算 Oceanus

呼叫医生云! Amazon HealthLake 现已正式上线

亚马逊云科技 (Amazon Web Services)

AI ML

Flink 实践教程-进阶(6):CEP 复杂事件处理

腾讯云大数据

流计算 Oceanus

Mycat 作为代理服务端的小知识点

CRMEB

数云运维总监陈延宗:基于阿里云计算巢,数云CRM一键云上交付

阿里云弹性计算

弹性计算 年度峰会 计算巢

圆桌对话:云时代下,企业运维面临的挑战与机遇

阿里云弹性计算

运维峰会 圆桌对话

百度APP浏览内核资源加载优化实践 -- ResourceScheduler 调优机制

百度开发者中心

百度app

代码审计思路之PHP代码审计

网络安全学海

网络安全 信息安全 渗透测试 安全漏洞 代码审计

只需5步!在轻量应用服务器部署Hexo博客

阿里云弹性计算

Hexo 轻量征文 用户投稿

聊聊Netty那些事儿之Reactor在Netty中的实现(创建篇)

bin的技术小屋

网络编程 socket nio netty java 编程

如何使团队的git log更优雅

阿呆

#GitLab

5个步骤构建优质Redis模块_文化 & 方法_翻译自redis.io_InfoQ精选文章