Redis 数据类型
String - 字符串类型
Hash - Hash类型
List - 列表类型
Set - 集合类型
Zset - 有序集合类型
String 字符串类型
String 是Redis 最基本的类型
String 类型是二进制安全的,意味着Redis 的String 可以包含任何数据,比如jpg 图片或者序列化的对象。
常用命令
- append key value 将给定的value 追加到原值的末尾
- strlen key 获取值的长度
- setnx key value 只有在key 不存在时,设置key 的值。(set 命令key 存在时直接覆盖原有的值)
- msetnx 同时设置多个,只要有一个已存在就都失败
- getrange key 起始位置 结束位置 :获得值的范围,起始位置和结束位置都包括,类似Java 中的substring
- setrange key 起始位置 value :用value 覆盖key 所存储的字符串值,从起始位置开始
- setex key 过期时间 value :设置键值的同时,设置过期时间,单位秒
- getset key value :以新换旧,设置了新值同时获得旧值。
Redis 这些命令都是原子操作,因为Redis 是单线程操作的,不同于Java 是多线程操作,如i++ 是非原子操作。
数据结构
String 的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。是可以修改的字符串,内部结构实现上类似Java 的ArrayList ,采用预分配冗余空间的方式来减少内存的频繁分配。
如图所示:内部为当前字符串实际分配的空间capacity 一般要高于实际字符串长度len。当字符串长度小于1M 时,扩容都是加倍现有的空间,如果超过1M ,扩容时一次只会多扩1M 的空间。需要注意的是字符串最大长度为512M。
Hash 键值类型
Redis Hash 是一个键值对集合,类似Java 里的Map<String, Object>。
Hash类型用于存储结构化数据
Hash命令
- hkeys key :列出该hash 集合的所有field
- hvals key :列出该hash 集合的所有value
- hincrby key field increment :为哈希表key 中的域field 的值加上增量 1 -1
- hsetnx key field value :将哈希表 key 中域 field 的值设置为value ,当且仅当域field 不存在
数据结构
Hash 类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value 长度较短且个数较少时,使用ziplist ,否则使用hashtable。
List 列表类型
List列表就是一系列字符串的“数组”,按插入顺序排序。
List列表最大长度为2的32次方-1,可以包含40亿个元素。
它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
List命令
- rpush listkey c b a - 右侧插入
- lpush listkey f e d - 左侧插入
- rpop listkey - 右侧弹出。值在键在,值光键亡;值都弹出了,键就没了
- lpop listkey - 左侧弹出
- lrange listkey start end - 列出listkey中从start开始到end所有元素,如果end 是-1 则全部列出
- rpoplpush key1 key2 :从key1 列表右边吐出一个值,插到key2 列表左边
- index key index :按照索引下标获得元素
- llen key :获得列表长度
- insert key before/after value newvalue :在value的前/后面插入newvalue值
- lrem key n value :从左边删除n 个value
- lset key index value :将列表key 下标为index 的值替换为 value
数据结构
List 的数据结构为快速链表 quickList
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist ,也即是压缩列表。
它将所有的元素紧挨着一起存储,分配的是一块连续的内存。
当数据量比较多的时候才会改成quicklist。
因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int 类型的数据,结构上还需要两个额外的指针 prev 和 next。
Redis 将链表和ziplist 结合起来组成了 quicklist。也就是将多个ziplist 使用双向指针串起来使用。这样即满足了快速的插入删除性能,又不会出现太大的空间冗余。
Set 集合类型
Set集合是字符串的无序集合,集合成员是唯一的。它底层其实是一个value 为null 的hash 表,所以添加、删除、查找的复杂度都是O(1)。(O(1)是随着数据的增加,查找数据的时间不变)
常用命令
- sadd key value1 value2 … :将一个或多个value 元素加入到key 中,已存在的 value 元素将被忽略
- smembers key :取出该集合的所有值
- sinter set1 set2 :返回两个集合的交集元素
- sunion set1 set2 :返回两个集合的并集元素
- sdiff set1 set2 :返回两个集合的差集元素(set1 中的,不包含set2 中的)
- sismenber key value :判断集合key 是否为含有该value 值,有1,没有0
- scard key :返回该集合的元素个数
- srem key value1 value2 … :删除集合中的某个元素。
- spop key :随机从该集合中吐出一个值
- srandmember key n :随机从该集合中取出n 个值,不会从集合中删除。
- smove source destination value :把集合中一个值从一个集合移动到另一个集合
数据结构
Set 数据结构是dict 字典,字典是用哈希表实现。
Java 中 HashSet 的内部实现使用的是 HashMap ,只不过所有的value 都指向同一个对象。
Redis 的Set 结构也是一样的,它的内部也使用Hash 结构,所有的value 都指向同一个内部值。
Zset 集合类型
Zset集合是字符串的有序集合,集合成员是唯一的。
有序集合的每个成员都关联了一个评分(score),这个评分被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复的。
常用命令
- zadd key score1 value1 score2 value2 … :将一个或多个member 元素及其score 值加入到有序集合key 当中。
- zrange key start stop [withscores] :返回有序集key 中,下标在start stop 之间的元素,stop 为-1 则到尾部的所有元素。带withscores 则可以让分数和值一起返回到结果集。
- zrangebyscore key min max [withscores] [limit offset count] :返回有序集合key 中,所有score 值介于min 和max 之间(包括等于min 或max)的成员。有序集合成员按score 值递增次序排序。
- zrevrangebyscore key max min [withscores] [limit offset count] :同上,改为从大到小排序。
- zincrby key increment value :为元素的score 加上增量
- zrem key value :删除该集合下指定值的元素
- zcount key min max :统计该集合分数区间内的元素个数
- zrank key value :返回该值在集合中的排名,从0 开始。
数据结构
zset 底层使用了两个数据结构
- hash ,hash 的作用就是关联元素 value 和权重score ,保障元素value 的唯一性,可以通过元素value 找到响应的score 值。
- 跳跃表,跳跃表的目的在于给元素value 排序,根据score 的范围获取元素列表。
跳跃表
跳跃表效率堪比红黑树,实现远比红黑树简单。
对比有序链表和跳跃表,查询出51
- 有序链表
需要从第一个元素开始依次比较查找,供需要6 次比较。 - 跳跃表
从第2 层开始,先找到21,再到第1 层,找到41,再到第0 层,找到51,供比较了4次。