深刻了解Redis(4)-类型检查与命令多态

Redis 中用于操做键的命令基本上能够分为两种类型。redis

其中一种命令能够对任何类型的键执行, 好比说 DEL 命令、 EXPIRE 命令、 RENAME 命令、 TYPE 命令、 OBJECT 命令, 等等。数据库

而另外一种命令只能对特定类型的键执行, 好比说:服务器

  • SET 、 GET 、 APPEND 、 STRLEN 等命令只能对字符串键执行;
  • HDEL 、 HSET 、 HGET 、 HLEN 等命令只能对哈希键执行;
  • RPUSH 、 LPOP 、 LINSERT 、 LLEN 等命令只能对列表键执行;
  • SADD 、 SPOP 、 SINTER 、 SCARD 等命令只能对集合键执行;
  • ZADD 、 ZCARD 、 ZRANK 、 ZSCORE 等命令只能对有序集合键执行;

类型检查的实现

在执行一个类型特定的命令以前, Redis 会先检查输入键的类型是否正确, 而后再决定是否执行给定的命令。函数

类型特定命令所进行的类型检查是经过 redisObject 结构的 type 属性来实现的:编码

  • 在执行一个类型特定命令以前, 服务器会先检查输入数据库键的值对象是否为执行命令所需的类型, 若是是的话, 服务器就对键执行指定的命令;
  • 不然, 服务器将拒绝执行命令, 并向客户端返回一个类型错误。

举个例子, 对于 LLEN 命令来讲:code

  • 在执行 LLEN 命令以前, 服务器会先检查输入数据库键的值对象是否为列表类型, 也便是, 检查值对象 redisObject 结构 type 属性的值是否为 REDIS_LIST , 若是是的话, 服务器就对键执行 LLEN 命令;
  • 不然的话, 服务器就拒绝执行命令并向客户端返回一个类型错误;

过程如图:对象

多态命令

Redis 除了会根据值对象的类型来判断键是否可以执行指定命令以外, 还会根据值对象的编码方式, 选择正确的命令实现代码来执行命令。blog

举个例子, 在前面介绍列表对象的编码时咱们说过, 列表对象有 ziplist 和 linkedlist 两种编码可用, 其中前者使用压缩列表 API 来实现列表命令, 然后者则使用双端链表 API 来实现列表命令。ip

如今, 考虑这样一个状况, 若是咱们对一个键执行 LLEN 命令, 那么服务器除了要确保执行命令的是列表键以外, 还须要根据键的值对象所使用的编码来选择正确的 LLEN 命令实现:ci

  • 若是列表对象的编码为 ziplist , 那么说明列表对象的实现为压缩列表, 程序将使用 ziplistLen 函数来返回列表的长度;
  • 若是列表对象的编码为 linkedlist , 那么说明列表对象的实现为双端链表, 程序将使用 listLength 函数来返回双端链表的长度;

借用面向对象方面的术语来讲, 咱们能够认为 LLEN 命令是多态(polymorphism)的: 只要执行 LLEN 命令的是列表键, 那么不管值对象使用的是 ziplist 编码仍是 linkedlist 编码, 命令均可以正常执行。

图 8-19 展现了 LLEN 命令从类型检查到根据编码选择实现函数的整个执行过程, 其余类型特定命令的执行过程也是相似的。