redis学习(二) redis数据结构介绍以及常用命令
redis数据结构介绍
我们已经知道redis是一个基于key-value数据存储的数据结构数据库,这里的key指的是string类型,而对应的value则可以是多样的数据结构。其中包括下面五种类型:
1.string 字符串
string字符串类型是redis最基础的数据存储类型。string是最基础的一种数据类型,其可以拓展为某种特定类型,例如普通文本,json字符串,二进制数据等等。就本质上来说,接下来要介绍的hash,list,set等其内部最基础的组成单位依然是string,只不过redis允许使用者以一种更加高效的方式处理某种数据结构的内部单元数据,这也是redis相对于memcached的一大优势。
2.hash 散列
hash散列类型也是一种key-value形式的字典数据类型,存储了key->value的映射,和redis本身一样,其依然被限制为只允许字符串类型作为key值。同时value并不支持嵌套的数据结构,而只能是字符串类型(应该是为了保证redis设计的简单性,以及高性能(嵌套结构越深,效率越低下),因此数据结构都不允许嵌套)。redis的hash类型适合存储对象,比起json字符串的形式,在仅仅访问对象的部分属性时,能够避免不必要的cpu运算和数据传输,大大的提高了效率的同时也便于进行并发时的控制。
3.list 列表
list列表类型可以存储一个有序的字符串类型列表,其常用操作为从列表的首尾添加或者获得元素、获取列表某一部分的数据等。由于list类型需要支持比较高效的首尾添加和删除操作,因此其内部实现采用了双向链表,保证了首尾对称操作效率的统一。同时,借助列表也能够实现队列的功能。
4.set 集合
set集合类型拥有hash的部分特性,其内部实现采用的是value为空的hashTable(散列表),因此具有高效的查询效率(O(1)时间复杂度),存储的数据具有唯一性。set类型的常用操作除了通用的添加,删除元素之外,还拥有集合类型独有的获得多个集合的交集,并集,差集的操作。
5.sorted set 有序集合
sorted set有序集合类型是和上述的set集合类型紧密相关的,顾名思义就是排序好了的集合。最大的区别在于存储数据时,除了通用的value之外,还包括了score属性作为排序的依据。有序集合同时拥有了list列表类型(有序)和set集合类型(value唯一)的特点。其和列表不同的是,有序集合类型内部实现采用的是hashTable(散列表)和skipList(跳跃表)。因此其访问位于中间部分的数据效率也比较高(O(nlogn)时间复杂度 ),而list类型访问中间部分元素的渐进意义下的时间复杂度则为O(n)。
天下没有免费的午餐,在通过散列表和跳跃表具有较快的查询速度的同时,同等数据量的情况下其消耗的内存相比双向链表为基础的list类型要高出不少,是一种空间换时间的做法,在决定使用有序集合时需要进行一定的权衡,避免不必要的系统资源浪费。
redis数据结构常用命令
redis提供了非常丰富的关于数据结构操作的各种命令。redis命令原则上不区分大小写(这里默认全部大写),而key值区分大小写
限于篇幅,这里只介绍比较常用的命令,要想了解更多的细节,最好的办法还是查看redis提供的文档进行学习。
1.string 字符串 常用命令
1.1 SET GET
SET 接口定义:SET key "value"
接口描述:存储一个key-value键值对,如果之前key已经存在,覆盖之前的value。
GET 接口定义:GET key
接口描述:通过key,返回对应的value,如果key不存在返回nil。
1.2 INCR
INCR 接口定义:INCR key
接口描述:将key对应的value增加1,并返回执行之后的数据(之前key不存在,默认value为0)。如果value无法解析为数字类型,则抛出异常。
1.3 DECR
DECR 接口定义:DECR key
接口描述:将key对应的value减少1,并返回执行之后的数据(之前key不存在,默认value为0)。如果value无法解析为数字类型,则抛出异常。
1.4 INCRBY DECRBY
INCRBY 接口定义: INCRBY key "increment"
接口描述: 将key对应的value减少参数increment,并返回执行之后的数据(之前key不存在,默认value为0)。如果increment/value无法解析为数字类型,则抛出异常。
DECRBY 接口定义: DECRBY key "decrement"
接口描述: 将key对应的value减少参数decrement,并返回执行之后的数据(之前key不存在,默认value为0)。如果decrement/value无法解析为数字类型,则抛出异常。
1.5 STRLEN
STRLEN 接口定义 : STRLEN key
接口描述:返回key对应的value的字符串长度。
1.6 APPEND
APPEND 接口定义:APPEND key "value"
接口描述:在key对应的value后面添加后缀,并且返回执行之后value的字符串长度。
1.7 string类型其它常用命令
字符串类型的常用命令还有诸如MGET(同时获取多个key的数据),MSET(同时设置多个key的数据),INCRBYFLOAT(增加一个浮点数值),DECRBYFLOAT(减少一个浮点数值),BITOP(位运算)等等。
2.hash 散列 常用命令
2.1 HSET HGET
HSET 接口定义: HSET key "field" "value"
接口描述:为key对应的Hash类型元素添加一个key-value键值对。
HGET 接口定义: HGET key "field"
接口描述:获得key对应的Hash类型元素的某一field的value值。
2.2 HMSET HMGET (M代表multi,多选的含义)
HMSET 接口定义: HMSET key "field1" "value1" ["field2" "value2" "field3" "value3" ...]
接口描述:为key对应的Hash类型元素添加一个或多个key-value键值对。
HMGET 接口定义: HMGET key "field1" ["field2" "field3" ...]
接口描述:获得key对应的Hash类型元素一个或多个field的value值。
2.3 HGETALL
HGETALL 接口定义: HGETALL key
接口描述:获得key对应的Hash类型元素的所有key以及value值。
2.4 HEXISTS
HEXISTS 接口定义: HEXISTS key "field"
接口描述: 判断key对应的Hash类型元素是否存在某一field,返回1代表存在,返回0代表不存在。
2.5 HDEL
HDEL 接口定义: HDEL key "filed1" ["field2","field3" ...]
接口描述:删除key对应的Hash类型元素一个或多个field值,返回实际被删除的field个数。
2.6 HLEN
HLEN 接口定义:HLEN key
接口描述: 获得key对应的Hash类型元素当前存在的field的数量。
2.7 hash类型其它常用命令
hash类型的常用还有诸如HKEYS(获得对应hash元素的所有field的值),HVALS(获得对应hash元素的所有field的value值),HINCRBY(使对应hash元素的某一field的value值增加),HDECRBY(使对应hash元素的某一field的value值减少)等等。
3.List 列表类型 常用命令
3.1 LPUSH RPUSH
LPUSH 接口定义:LPUSH key "value1" ["value2","value3" ...]
接口描述:在对应key的列表元素头部(left 左侧)依次插入一个或多个数据节点,返回最终的列表长度。
RPUSH 接口定义 :RPUSH key "value1" ["value2","value3" ...]
接口描述:在对应key的列表元素尾部(right 右侧)依次插入一个或多个数据节点,返回最终的列表长度。
3.2 LPOP RPOP
LPOP 接口定义:LPOP key
接口描述:返回对应key的列表元素头部(left 左侧)弹出(获得元素,并且从列表中移除)第一个数据节点。
RPOP 接口定义:RPOP key
接口描述:返回对应key的列表元素尾部(right 右侧)弹出(获得元素,并且从列表中移除)第一个数据节点。
3.3 LLEN
LLEN 接口定义:LLEN key
接口描述:返回对应key的列表元素拥有的数据节点个数
3.4 LRANGE
LRANGE 接口定义:LRANGE key "start" "stop"
接口描述:返回对应key的列表元素 从start->stop下标之间的所有数据节点(和python一样,支持负数下标(从末尾开始计算))。
3.5 LREM
LREM 接口定义:LREM key "count" "value"
接口描述:对应key的列表元素删除(count个)值为value的数据节点。
潜规则:当count > 0时,从左到右匹配和删除,count < 0时,从右到左匹配和删除,count = 0时,删除全部匹配的数据节点。
3.6 LINDEX
LINDEX 接口定义:LINDEX key "index"
接口描述:返回对应key的列表元素第index个数据节点,支持负数下标(从末尾开始计算)。
3.7 LSET
LSET 接口定义:LSET key "index" "value"
接口描述:将对应key的列表元素中位于index下标位置的数据赋值为value(如果下标越界,会抛出异常)。
3.8 list列表类型其它常用命令
list类型的常用还有诸如LTRIM(截取列表),LINSERT(向列表指定下标位置插入数据),RPOPLPUSH(将数据节点从一个列表转移到另一个列表)等等。
4.set集合类型 常用命令
4.1 SADD SREM
SADD 接口定义:SADD key "member1" ["member2","member3" ...]
接口描述: 在对应key的集合元素中插入一到多个数据,返回实际被插入的数据个数(已经存在的数据不会被重复插入)。
SREM 接口定义:SREM key "member1" ["member2","member3" ...]
接口描述: 在对应key的集合元素中移除一到多个数据,返回实际被删除的数据个数(不存在的数据不会被计算)。
4.2 SMEMBERS
SMEMBERS 接口定义:SMEMBERS key
接口描述:返回key对应的集合元素中所有数据。
4.3 SISMEMBER
SISMEMBER 接口定义:SISMEMBER key "member"
接口描述:判断member是否存在于key对应的集合元素中,如果存在返回 1,如不存在返回 0。
4.4 SINTER SUNION SDIFF
SINTER 接口定义:SINTER "key1" ["key2","key3" ...]
接口描述:获得一个或多个集合的交集。
SUNION 接口定义:SUNION "key1" ["key2","key3" ...]
接口描述:获得一个或多个集合的并集。
SDIFF 接口定义:SDIFF "key1" ["key2","key3" ...]
接口描述:获得一个或多个集合的差集,多个集合从左到右,进行运算。
4.5 SCARD
SCARD 接口描述:SCARD key
接口描述: 返回key对应的集合元素中数据的个数。
4.6 set类型其它常用命令
set类型的常用命令还有诸如SINTERSTORE,SUNIONSTORE,SDIFFSTORE(取得交集、并集、差集的结果,同时保存为另一个集合),SRANDERMEMBER(从集合中随机获得元素),SPOP(从集合中随机弹出元素)等等。
5.sorted set有序集合类型 常用命令
5.1 ZADD ZREM
ZADD 接口定义:ZADD key "score1" "member1" ["score2","member2","score3","member3" ...]
接口描述:在key对应的有序集合中插入一到多个 score->member 键值对,返回实际插入的数据(已经存在的数据不会被重复插入)。
ZREM 接口定义:ZREM key "member1" ["member2","member3" ...]
接口描述:在key对应的有序集合中删除一到多个数据,返回实际被删除的数据个数(不存在的数据不会被计算)。
5.2 ZSCORE
ZSCORE 接口定义:ZSCORE key member
接口描述:返回key对应的有序集合某一member对应score的值。
5.3 ZRANGE ZREVRANGE
ZRANGE 接口定义:ZRANGE key start stop
接口描述:key对应的有序集合按照score从小到大的顺序,返回索引在start和stop之间的数据。
ZREVRANGE 接口定义:ZREVRANGE key start stop
接口描述:key对应的有序集合按照score从大到小的顺序,返回索引在start和stop之间的数据。
5.4 ZINCRBY
ZINCRBY 接口定义:ZINCRBY key "increment" "member"
接口描述:key对应的有序集合的某一个member增加"incrment"(可以为负数),并且返回执行完毕的结果。
5.5 ZCARD
ZCARD 接口定义:ZCARD key
接口描述:返回key对应的有序集合中数据的数量。
5.6 zset类型其它常用命令
zset类型的常用命令还包括ZRANGEBYSCORE, ZREVRANGEBYSCORE(按照score范围来进行顺序查找)、ZREM(移除集合内数据)等等。
6. redis数据结构相关常用命令总结
redis的数据结构相关命令还有很多,限于篇幅,上面只是简要描述了个人认为比较常用的命令。要想更加深入的理解这一部分内容,还是应该从官方文档,教学书籍入手,反复的尝试练习并且在工作中将其实践。
redis的设计是很优雅的,命令接口大多是正交的,使用者可以很直观的从命令的名称、参数定义,快速的理解命令的使用方法。但是,我认为例如SRANDERMEMBER,SREM等命令设计的过于灵活,同一参数可以因为处于不同数据范围而导致接口的行为完全不同,使得使用者被迫需要记住接口的一套独有规则。这时不如设计多个不同的简单接口分开实现功能来的简单直接。毕竟,有时过于简单反而会导致不必要的复杂性。