类型检查与命令多态
2023-3-28
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
Redis中用于操作键的命令基本上可以分为两种类型。
一种命令可以对任何类型的键执行, 比如说 DEL 命令、 EXPIRE命令、 RENAME命令、 TYPE命令、 OBJECT命令, 等等。
使用DEL命令来删除三种不同类型的键:
而另一种命令只能对特定类型的键执行, 比如说:
  • SET 、 GET 、 APPEND 、 STRLEN 等命令只能对字符串键执行
  • HDEL 、 HSET 、 HGET 、 HLEN 等命令只能对哈希键执行
  • RPUSH 、 LPOP 、 LINSERT 、 LLEN 等命令只能对列表键执行
  • SADD 、 SPOP 、 SINTER 、 SCARD 等命令只能对集合键执行
  • ZADD 、 ZCARD 、 ZRANK 、 ZSCORE 等命令只能对有序集合键执行
 

类型检查的实现

为了确保只有指定类型的键可以执行某些特定的命令, 在执行一个类型特定的命令之前, Redis会先检查输入键的类型是否正确, 然后再决定是否执行给定的命令。
类型特定命令所进行的类型检查是通过 redisObject 结构的 type 属性来实现的:
  • 在执行一个类型特定命令之前, 服务器会先检查输入数据库键的值对象是否为执行命令所需的类型, 如果是的话, 服务器就对键执行指定的命令;
  • 否则, 服务器将拒绝执行命令, 并向客户端返回一个类型错误。
 
例如,对于LLEN命令来说:
notion image
 

多态命令的实现

Redis除了会根据值对象的类型来判断键是否能够执行指定命令之外, 还会根据值对象的编码方式, 选择正确的命令实现代码来执行命令。
例如,列表对象有 ziplist 和 linkedlist 两种编码可用, 其中前者使用压缩列表 API 来实现列表命令, 而后者则使用双端链表 API 来实现列表命令。如果对一个键执行 LLEN 命令, 那么服务器除了要确保执行命令的是列表键之外, 还需要根据键的值对象所使用的编码来选择正确的 LLEN 命令实现:
  • 如果列表对象的编码为 ziplist , 那么说明列表对象的实现为压缩列表, 程序将使用 ziplistLen 函数来返回列表的长度
  • 如果列表对象的编码为 linkedlist , 那么说明列表对象的实现为双端链表, 程序将使用 listLength 函数来返回双端链表的长度
借用面向对象方面的术语来说, 可以认为 LLEN 命令是多态的: 只要执行 LLEN 命令的是列表键, 那么无论值对象使用的是 ziplist 编码还是 linkedlist 编码, 命令都可以正常执行。
notion image
实际上, 可以将 DEL 、 EXPIRE 、 TYPE 等命令也称为多态命令, 因为无论输入的键是什么类型, 这些命令都可以正确地执行。
DEL 、 EXPIRE 等命令和 LLEN 等命令的区别在于, 前者是基于类型的多态 —— 一个命令可以同时用于处理多种不同类型的键, 而后者是基于编码的多态 —— 一个命令可以同时用于处理多种不同编码。
  • Redis
  • Stream 消息队列内存回收和对象共享
    目录