一、数据结构简介
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
Redis 所有的数据结构都是以唯一的 key 字符串作为名称,然后通过这个唯一 key 值来获取相应的 value 数据。不同类型的数据结 构的差异就在于 value 的结构不一样。
使用桌面工具查看,默认有16个库,Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。
1、String(字符串)
string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
Redis 的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配,如图中所示,内部为当前字符串实际分配的空间 capacity 一般要高于实际字符串长度 len。当字符串长度小于 1M 时, 扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。需要注意的是 字符串最大长度为 512M。
使用基本命令 即可
set keyname test
get keyname
桌面工具查看结构
key-value
2、Hash(哈希)
Redis hash 是一个键值(key=>value[k-v])对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
Redis 的字典相当于 Java 语言里面的 HashMap,它是无序字典。内部实现结构上同 Java 的 HashMap 也是一致的,同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞 时,就会将碰撞的元素使用链表串接起来。
每个 hash 可以存储 232 -1 键值对(40多亿)。
hmset myhash field1 "Hello" field2 "World"
hget myhash field1
hget myhash field2
桌面工具查看结构
key field1 value
field2 value
3、List(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
Redis 的列表相当于 Java 语言里面的 LinkedList,注意它是链表而不是数组。这意味着 list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n).
当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。
列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。
lpush mylist redis
lpush mylist rabbitmq
lpush mylist spring
lrange mylist 0 10
桌面工具查看结构【链表】
key value1
value2
用途:Redis 的列表结构常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符 串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。
4、Set(集合)
Redis的Set是string类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。它的 内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL。
当集合中最后一个元素移除之后,数据结构自动删除,内存被回收。 set 结构可以用来 存储活动中奖的用户 ID,因为有去重功能,可以保证同一个用户不会中奖两次。
集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。
4.1、无序集合【sadd命令】
添加一个 string 元素到 key 对应的 set 集合中,成功返回1,如果元素已经在集合中返回 0,如果 key 对应的 set 不存在则返回错误。
sadd key member
127.0.0.1:6379> sadd myset redis (integer) 1 127.0.0.1:6379> sadd myset spring (integer) 1 127.0.0.1:6379> sadd myset rabbitmq (integer) 1 127.0.0.1:6379> sadd myset rabbitmq (integer) 0 127.0.0.1:6379> smembers myset 1) "redis" 2) "rabbitmq" 3) "spring"
注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。
桌面工具查看结构【无序不重复集合】
key value1
value2
5、有序集合zset(sorted set)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
zset 可能是 Redis 提供的最为特色的数据结构,它也是在面试中面试官最爱问的数据结 构。它类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权 重。它的内部实现用的是一种叫着「跳跃列表」的数据结构。
zset 中最后一个 value 被移除后,数据结构自动删除,内存被回收。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
zadd 命令
添加元素到集合,元素在集合中存在则更新对应score
zadd key score member
127.0.0.1:6379> zadd myzset 0 redis (integer) 1 127.0.0.1:6379> zadd myzset 0 mongodb (integer) 1 127.0.0.1:6379> zadd myzset 0 rabbitmq (integer) 1 127.0.0.1:6379> zadd myzset 1 basic (integer) 1 127.0.0.1:6379> zadd myzset 0 rabbitmq (integer) 0 127.0.0.1:6379> zrangebyscore myzset 0 1000 1) "mongodb" 2) "rabbitmq" 3) "redis" 4) "basic"
桌面工具查看结构【有序不重复集合】
key value2 0 value3 0 value1 1
二、容器型数据结构的通用规则
list/set/hash/zset 这四种数据结构是容器型数据结构,它们共享下面两条通用规则:
1、create if not exists
如果容器不存在,那就创建一个,再进行操作。比如 rpush 操作刚开始是没有列表的,Redis 就会自动创建一个,然后再 rpush 进去新元素。
2、drop if no elements
如果容器里元素没有了,那么立即删除元素,释放内存。这意味着 lpop 操作到最后一个元素,列表就消失了。
3、过期时间
Redis 所有的数据结构都可以设置过期时间,时间到了,Redis 会自动删除相应的对象。 需要注意的是过期是以对象为单位,比如一个 hash 结构的过期是整个 hash 对象的过期, 而不是其中的某个子 key。
特别注意:如果一个字符串已经设置了过期时间,然后你调用了set 方法修改了它,它的过期时间会消失。