【AICon】 如何构建高效的 RAG 系统?RAG 技术在实际应用中遇到的挑战及应对策略?>>> 了解详情
写点什么

Set 命令是一个怪兽

  • 2019-10-24
  • 本文字数:2422 字

    阅读完需:约 8 分钟

Set命令是一个怪兽

Helicoprion(旋齿鲨)是一种现已灭绝但奇怪的动物,它生活在二叠纪早期的海洋中,它在尺寸和形状上与现代大白鲨看起来或多或少相似,它曾经是海洋中强大的掠夺者,因其下颌上长着排列成螺旋状的牙齿而得名,这有点类似于在下颚内部放置一个带有鲨鱼齿的圆锯,但这不符合生物的进化论,因此我们现在看不到这样的物种了。


在某些方面,Redis SET 命令就像旋齿鲨,但它仍然在全球范围内的大量 Redis 服务器上被使用。SET 是一个非常早期的命令,具有一些非常有用、不寻常的功能,但是在深度使用的同时可能存在风险。


SET 命令看起来很简单直接,我们在学习 Redis 的时候通常将它用作第一个命令,我们使用它进行简单的测试以确保 Redis 正常工作。比如:


> SET foo bar
复制代码


表面上没什么特别的,但它隐藏了什么吗?

SET 命令:一种数据的破坏者

回到我们简单的 SET 示例。让我们模拟一个更复杂的场景:


> UNLINK foo(integer) 1> HSET foo bar 123(integer) 1> SET foo barOK
复制代码


有没有用 SET 发现这里的怪异?现有的键 foo 是 hash 类型(由于 HSET),但是当我之后立即运行 SET 时它仍然可以正常工作。与其他 Redis 命令相比,这实际上非常奇怪。让我们采取相同的命令,但对最后两个命令使用相反的顺序:


> UNLINK foo(integer) 1> SET foo barOK> HSET foo bar 123(error) WRONGTYPE Operation against a key holding thewrong kind of value
复制代码


您可以看到 SET 忽略键的存在或类型,并始终写入,另一方面,哈希在面对不同类型的非空键时会抛出错误。除了字符串之外的所有数据类型都是如此,特别是 SET 命令和一些衍生的命令(PSETEX,SETEX,MSET),例如:


 > HSET foo bar 123(integer) 1> APPEND foo bar(error) WRONGTYPE Operation against a key holding thewrong kind of value> INCR foo(error) WRONGTYPE Operation against a key holding thewrong kind of value> SETBIT foo 1 1(error) WRONGTYPE Operation against a key holding thewrong kind of value> BITFIELD foo SET u8 0 1(error) WRONGTYPE Operation against a key holding thewrong kind of value> INCRBY foo 1(error) WRONGTYPE Operation against a key holding thewrong kind of value> INCRBYFLOAT foo 1(error) WRONGTYPE Operation against a key holding thewrong kind of value> SETRANGE foo 1 barbar(error) WRONGTYPE Operation against a key holding thewrong kind of value
复制代码


SETNX 和 SET … NX(稍后会详细介绍)是一个有趣的旁注,如果键不存在,它们将设置 SET,如果设置了则返回 1,否则返回 0。因此,它不会进行类型检查,而是进行状态检查。


总而言之,SET 不关心键是什么类型,它都会覆盖,很少有其他命令能够挡住它前进的道路。

一种 TYPE,三种类型

如果您已经在 Redis 中遇到过几次,那么您就知道可以使用 TYPE 命令查询存储在键中的数据类型。举个例子,让我们回到 foo:


 > SET foo barOK> TYPE foostring
复制代码


您可以很容易地在键 foo 上设置值“bar”。现在让我们看看别的东西:


> SET foo 1234OK> TYPE fooString> GETRANGE foo 2 3"34"
复制代码


因此,您可能会认为数字 1234 被存储为字符,这时候可以说你的想法或多或少是正确的,但是,请继续往下看:


> INCR foo(integer) 1235> GETRANGE foo 2 3"35"
复制代码


这说明 Redis 将字符理解为文本和数字 - 您可以将其视为松散的类型, 但它很奇怪:


> SET foo "hello world"OK> INCR foo(error) ERR value is not an integer or out of range
复制代码


显然,Redis 不能对非数字执行 INCR。但请继续看, Redis 也能理解浮点值,举个例子:


> SET foo 1.2OK> INCR foo(error) ERR value is not an integer or out of range> INCRBYFLOAT foo 0.8"2"> INCR foo(integer) 3
复制代码


您可以看到初始值是作为 float 放入的,因此 INCR(对于整数)将不起作用,但是,INCRBYFLOAT 确实有效,这 1.2 + 0.8 = 2 会将值更改为前一个 INCR 命令允许使用的整数。

一个命令,多种参数

该命令的另一个独特之处在于能够提供两类可选参数:一类用于到期,另一类用于存在检查。我们来看看第一个类别:到期参数。


对于大多数命令,如果要立即使键过期,则需要立即发出 EXPIRE 或 PEXPIRE,最常见的是在 MULTI / EXEC 事务中。例如:


> MULTIOK> SADD baz alpha beta gammaQUEUED> EXPIRE baz 10QUEUED> EXEC1) (integer) 32) (integer) 1
复制代码


这样可以确保在 SADD 和 EXPIRE 命令之间不会有其他命令执行,在 EXEC 执行完成之后你会有一个在 10 秒之后过期的集合。但是,使用 SET,您可以在没有事务的情况下达到这样的效果。


> SET foo bar EX 10OK
复制代码


或者,您可以使用 PX 而不是 EX 参数,使得来以毫秒而不是秒为单位到期。这是一个小技巧,也可以用 SETEX 和 PSETEX 实现, 我认为这些命令在提供便利的同时会降低可读性和灵活性。


另一类参数 NX / XX 可以控制 SET 命令在键存在或不存在时的行为,仅当键不存在时,NX 的键才会设置值。举个例子:


> UNLINK foo(integer) 0> SET foo 1234 NXOK> GET foo"1234"> SET foo 5678 NX(nil)> GET foo"1234"
复制代码


您可以看到第 4 个命令实际上没有做任何事情,因为键 foo 已经存在。这有很多用途:设置默认值而不覆盖现有数据,防止在用户在误操作输入时对键的以外覆盖。


与此相反的是 XX 命令,这仅在键已存在时设置值:


> UNLINK foo(integer) 1> SET foo 1234 XX(nil)> set foo 1234OK> SET foo 5678 XXOK
复制代码


这可用于将写入限制在已经定义过的键上。一种使用这个命令的场景是输入检查,只有在已经输入的情况下,才会把 Key 覆盖。

那么 SET 是一种危险的、不好的、不建议使用的命令?

绝对不是这样的,SET 是 Redis 中许多优秀实践的基础,但是它同时也具有许多与 Redis 其他命令根本不同的特性,重要的是要了解这些功能和命令如何工作,在此基础之上才能更好地组织 Redis 的键空间,以及在应用程序中正确的使用 Redis。


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


原文链接:


https://mp.weixin.qq.com/s/2JCBL6bkRSz_B0qnWia2gg


2019-10-24 16:07515

评论

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

阿里云瑶池 PolarDB 开源官网焕新升级

阿里云数据库开源

polarDB PolarDB-X PolarDB-PG 阿里云PolarDB

九科信息中标招商局集团流程挖掘项目

九科Ninetech

案例 | 基于机理模型驱动的工业APP集成开发平台及应用实践

工赋开发者社区

Code片段

Bert

打翻夏日调色盘,华为与你多巴胺一“夏”

最新动态

永续期权合约交易所系统开发案例(成品)

薇電13242772558

交易所

如何解决 Git 合并冲突

这我可不懂

git

MegEngine Python 层模块串讲(上)

MegEngineBot

Python 深度学习 开源 Data

提升 API 可靠性的五种方法

高端章鱼哥

测试 API API网关

Flink SQL 双表 JOIN 介绍与原理简析

腾讯云大数据

流计算 Oceanus

飞桨AI for Science线下交流会:汇聚科学计算人才,携手共建繁荣社区

飞桨PaddlePaddle

人工智能 百度 paddle 飞桨 百度飞桨

Docker学习路线9:运行容器

小万哥

c++ Docker 运维 后端 开发

PPT | 未来工厂与数字孪生

工赋开发者社区

虚幻引擎教程——生成云平台指定路径下的EXE文件

3DCAT实时渲染

虚幻引擎 ue UE虚幻引擎

使用 Python 处理 CSV 文件,附示例

前端毛小悠

Python

算网深度融合成趋势,天翼云让政企上云更安全、更便捷!

天翼云开发者社区

云计算 云平台

喜报!天翼云电脑获“光华杯”大赛一等奖、最佳创意创新奖!

天翼云开发者社区

云计算 云电脑

借助Databuff,快捷构建Kubernetes可观测能力

乘云 DataBuff

LLaVA:将视觉微调引入大模型

Zilliz

计算机视觉 LLM 大语言模型 模型微调

一些可以极大提高工作效率的 Linux 命令

互联网工科生

Linux 自动化运维

减少跨国传输大文件所需时间的技巧与工具

镭速

跨国传输大文件

QCA9880+MT7915 mini pcie card chip difference

wifi6-yiyi

wifi5

【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(系统底层优化篇)

洛神灬殇

MySQL 性能调优 技术分析 底层分析

上传了ipa但iTunes Connect没有构建版本问题

雪奈椰子

玩一玩编程式 AOP

江南一点雨

Java spring

文心一言 VS 讯飞星火 VS chatgpt (64)-- 算法导论6.5 3题

福大大架构师每日一题

福大大架构师每日一题

[分词]基于Lucene8版本的混合分词器(分词合并)

alexgaoyh

中文分词 lucene Spring Boot 2 混合模型

Code片段D

Bert

利用增强现实技术辅助跨国传输大文件的优化

镭速

唯一一家!国际测评:文心大模型3.5总分第一,算法模型第一,行业覆盖第一

飞桨PaddlePaddle

人工智能 百度 大模型 文心一言 文心大模型

酒有十千,棋有独步——本土大模型百花齐放,文心一言站稳领先者身位RlueEva-System大模型测评来了!你pick哪一家

TE智库

Set命令是一个怪兽_文化 & 方法_Kyle Davis_InfoQ精选文章