Redis对象类型检测与命令多态

一. 命令类型

        Redis中操作键的命令可以分为两类。

  • 一种命令可以对任意类型的键执行,比如说DEL,EXPIRE,RENAME,TYPE,OBJECT命令等。

举个例子:

#字符串键
127.0.0.1:6379> set msg "hello world"
OK
#列表键
127.0.0.1:6379> rpush number 1 2 3
(integer) 3
#集合键
127.0.0.1:6379> sadd fruits apple banana cherry
(integer) 3
127.0.0.1:6379> keys *
1) "number"
2) "msg"
3) "fruits"
127.0.0.1:6379> del msg
(integer) 1
127.0.0.1:6379> del fruits
(integer) 1
127.0.0.1:6379> del number
(integer) 1
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> 
  • 另一种命令是对特定类型的键执行 

1. SET, GET, APPEND,STRLEN等命令只能对字符串键使用。

2. HDEL, HSET, HGET,HLEN等命令只能对哈希键使用。

3. RPUSH, LPOP, LINSERT, LLEN等命令只能对列表键使用。

4. SADD, SPOP, SINTER, SCARD等命令只能对集合键使用。

5. ZADD, ZCARD, ZRANK, ZSCORE等命令只能对有序集合键使用。

例如:

        对字符串键使用,只能对列表键使用的LLEN命令,redis返回了一个类型错误。

127.0.0.1:6379> set msg "hello world"
OK
127.0.0.1:6379> get msg
"hello world"
127.0.0.1:6379> llen msg
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> 

 二.类型检测的实现

        从上面的报错可以看出,为了确保只有指定类型的键可以执行某些特殊命令,在执行一个类型特定的命令之前,Redis会先检测输入键的类型是否正确,然后再决定是否执行给定的命令。

        类型特定命令所进行的类型检查是通过redisObject结构中的type属性来实现的。

Redis对象类型检测与命令多态_第1张图片

        流程图如下:

Redis对象类型检测与命令多态_第2张图片

三. 多态命令的实现

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

        比如:列表对象的编码可以是ziplist或者linkedlist,其中前者使用压缩列表API实现列表命令,而后者则使用双端链表API来实现列表命令。

        假如,我们对一个键是哟个LLEN命令时,服务器除了需要确保执行命令的键是列表键,还需要根据键的编码选择正确的LLEN命令的实现:

  • 如果是ziplist编码,程序将使用ziplistlen函数返回列表长度。
  • 如果是linkedlist编码,程序将使用listlength函数返回双端链表的长度。

        借用面向对象的思想,我们可以认为LLEN命令是多态的,只需要执行LLEN命令的是列表键,不论是什么编码,都会执行成功。

        下图展示了LLEN命令从类型检查 到更具编码来选择实现函数的过程,其他类型特定命令的执行过程也类似:

Redis对象类型检测与命令多态_第3张图片

        实际上DEL, EXPIRE等命令也称之为多态命令,无论使用的是什么类型,这些命令都可以执行成功。

        DEL, EXPIRE命令和LLEN命令的去表在于,前者是基于类型多态,后者是基于编码多态。 

你可能感兴趣的:(Redis,redis)