Redis(三)基础:Redis五大基础数据类型
本文最后更新于:1 年前
前言
Redis官网:https://redis.io/docs/
Redis中文文档:http://www.redis.cn/topics/data-types-intro.html#strings
结合官网的学习一定是正确合理的,如果有命令或者理论我讲的不对,可以评论指出谢谢!
一、Redis数据类型介绍
Redis不仅只有key-value存储,实际上是一个数据结构服务器
,支持不同的数据类型,可以解决从缓存到队列再到事件处理的各种问题。
- Strings:二进制安全的字符串
- Lists:按插入顺序排序的字符串元素的集合。Redis 列表是字符串值的链表。(用于实现栈和队列)
- Sets:
不重复且无序
的字符串元素的集合 - Sorted sets:类似Sets,不同的地方在于每个字符串元素都关联一个叫
score
的浮动数值(floating number value)。里面的元素是按score进行排序。它可以检索一系列的元素。(可以直接看前10个元素或后10个元素) - Hashes:由field和关联的value组成的map。field和value都是字符串。实现类似于
哈希表
的概念。 - Bit arrays (或者说 simply bitmaps):通过特殊的命令,你可以将 String 值当作一系列 bits 处理:可以设置和清除单独的 bits,数出所有设为 1 的 bits 的数量,找到最前的被设为 1 或 0 的 bit,等等。
- HyperLogLog:是一种概率数据结构,这是被用于估计一个 set 中元素数量的概率性的数据结构。
二、Redis key
Redis key值是二进制安全的。
可以用任意二进制序列作为key值,如“linzy”简单字符串到JPEG文件的内容都可以作为key值。空值也是有效的key值。
关于key的几条规则:
键值不要太长
,例如:1024字节的键值不仅消耗大量内存,而且查询这个键值的成本也很高。键值不要太短
,就好是简洁表达含义的键值,例如:”u:1000:pwd”和”user:1000:password”,前者虽然简短,但是后者更容易阅读,一眼就知道键值的含义,并且后者增加的空间消耗相对较小。不过这个算个人习惯,没有人必须要求你该怎么写。坚持使用一种模式
,例如:”object-type : id : field”就是一个很不错的模式,像“user:1000:password”。对于多单词组合我习惯中间加_
隔离,比如:”comment:123456:linzy_dashuaige“。- key允许最大为 512 MB。
三、Redis Strings
1、字符串简介
Redis 字符串存储字节序列
,包括文本、序列化对象和二进制数组。因此,字符串是Redis最基本的数据类型。字符串用于缓存,通过提供的额外的功能也可以实现计算器以及按位运算。
2、字符串基本操作
1)通用命令
命令 | 描述 |
---|---|
set key value [NX | XX] [GET] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL] |
添加 / 修改一个键值对。 EX(expire):设置过期秒数 PX:设置过期毫秒数 EXAT:设置过期的Unix秒数 PXAT:设置过期的Unix毫秒数 KEEPTTL:set时不重置 ttl NX:只有当key不存在时添加一个新的键值对 XX:仅当key存在时覆盖当前value GET:修改一个键值并返回原值,如果原址不存在则返回nil |
get key | 获取key对应的value值。 注:key不存在会直接返回nil |
mset key1 value1 [key2 value2…] | 添加 / 修改一个或多个键值对。 |
mget key1 [key2…] | 获取key1 key2..获取对应的value1 value2 … |
注意:由于SET命令选项可以替换SETNX, SETEX, PSETEX, GETSET,因此在未来的 Redis 版本中,这些命令可能会被弃用并最终被删除。
1 |
|
2)value是字符串时操作
命令 | 描述 |
---|---|
append key value | 在key对应原有的value后追加内容。 注:如果键值对不存在,则会创建新的键值对,类似于set的功能 |
strlen key | 对应value的字符串值的长度。 注:如果value非字符串类型则返回错误 |
getrange key start end | 获取[start,end]范围内的子字符串。 注:可以使用 负偏移量 来提供从字符串末尾开始的偏移量。所以 -1 表示最后一个字符,-2 表示倒数第二个字符,依此类推。 |
1 |
|
3)value是数值的操作
有关于增量/减量操作,如果键值对不存在,则会默认创建一个值为0的键值对。增量/减量操作是原子操作
。
原子操作就是在多线程程序中“最小的且不可并行化的”操作,意味着多个线程访问同一个资源时,有且仅有一个线程能对资源进行操作。
命令 | 描述 |
---|---|
incr key | 将key对应的value加一。 |
incrby key 整数 | 将key对应的value增加给定的数值。 |
incrbyfloat key 小数值 | 将key对应的value增加给定的数值。 |
decr key | 将key对应的value减一。 |
decrby key 整数 | 将key对应的value增加给定的数值。 |
1 |
|
String 数据结构是简单的key-value 类型,
value 其实不仅是String,也可以是数字。
4)临时键值对的操作
生存时间(time to live),简称为ttl
,指键值对距离被删除的剩余时间(秒数或者毫秒数)
注:如果重新set设置生存时间,则会将之前的生存时间重置掉。
命令 | 描述 |
---|---|
expire key 秒数 | 给键值对设置一个生存时间。 注:超时后只有对key执行DEL命令或者SET命令或者GETSET时才会清除。从概念上讲所有改变key的值的操作都会使他清除。 |
ttl key | 查看当前键值对剩余生存时间。 注:key不存在则返回-2,永久键值对返回-1 |
pexpire key 毫秒数 | 毫秒版expire |
pttl key | 毫秒版ttl |
persist key | 持久化(取消生存时间) |
1 |
|
3、小结
Redis String 类型是可以与 Redis 键关联的最简单的值类型。Redis就像一个可以持久化的memcached服务器(注:memcache的数据仅保存在内存中,服务器重启后,数据将丢失)。
由于 Redis 的键是字符串,所以当我们也使用字符串类型作为值时,我们是在将一个字符串映射到另一个字符串。字符串数据类型可用于许多用例,例如缓存 HTML 片段或页面。
四、Redis Lists
1、列表简介
列表就是有序元素的序列,一般意义由两种数组(List)和链表(Linked List),例如 50,3,114514,20就是一个列表。
Redis lists基于链表实现。
这意味着即使在一个list中有数百万个元素,在头部或尾部添加一个元素的操作,其时间复杂度也是常数O(1)级别的。用LPUSH 命令在十个元素的list头部添加新元素,和在千万元素list头部添加新元素的速度相同。
那么,坏消息是什么?在数组实现的list中利用索引访问元素的速度极快,而同样的操作在链表实现的list上没有那么快。
Redis Lists用链表实现的原因是:对于数据库系统来说,至关重要的特性是:能非常快的在很大的列表上添加元素。另一个重要因素是,正如你将要看到的:Redis lists能在常数时间取得常数长度。
如果需要快速访问集合元素,建议使用可排序集合(sorted sets)。
2、列表基本操作
1)通用命令
命令 | 描述 |
---|---|
rpush key value0 [value1…] | 在列表尾部添加一个或多个value值。 |
lpush key value0 [value1…] | 在列表头部添加一个或多个value值。 |
rpushx key value0 [value1…] | 仅当列表存在时,在列表尾部添加一个或多个value值。 |
lpushx key value0 [value1…] | 仅当列表存在时,在列表头部添加一个或多个value值。 |
rpop key [整数] | 移除并返回存于 key 的 list 的尾部指定数值个元素。 注:与lpush组合可以实现队列,与rpush组合可以实现栈。 |
lpop key [整数] | 移除并返回存于 key 的 list 的头部指定数值个元素。 注:与rpush组合可以实现队列,与lpush组合可以实现栈。 |
lrange key start end | 查看[start,end]范围内的子序列。 注:lrange key 0 -1 查看列表所有值 |
1 |
|
2)数组操作
命令 | 描述 |
---|---|
lset key index value | 将指定index位置上的元素修改为value。 |
linsert key <before / after> pivot value | 在基准值pivot的前 / 后插入一个值。 |
lindex key index | 按索引查看值。 |
llen key | 查看列表长度。 |
lrem key 整数 value | 删除整数个指定数值。 注:整数为正从左开始删,为负从尾部开始删 |
ltrim key start end | 只保留[start, end]范围的列表。 |
1 |
|
列表索引从0开始,-n表示倒数第n个值。
3、小结
列表访问其头部或尾部的列表操作是 O(1),非常高效。但是,操作列表中元素的命令通常是 O(n)。这些示例包括LINDEX、LINSERT和LSET。运行这些命令时要小心,主要是在处理大型列表时。
列表可被用来实现聊天系统。还可以作为不同进程间传递消息的队列。
关键是,你可以每次都以原先添加的顺序访问数据。这不需要任何SQL ORDER BY 操作,将会非常快,也会很容易扩展到百万级别元素的规模。
例如在评级系统中,比如社会化新闻网站 reddit.com,你可以把每个新提交的链接添加到一个list,用LRANGE可简单的对结果分页。
在博客引擎实现中,你可为每篇日志设置一个list,在该list中推入博客评论,等等。
五、Redis Hashes
1、哈希简介
Redis 哈希是字符串字段和字符串值之间的映射。可以使用哈希来表示基本对象并存储计数器分组等。
2、哈希基本操作
1)通用命令
命令 | 描述 |
---|---|
hset key field1 value1 [field2 value2…] | 添加一个键与一或多个指定字段的值。 注:如果哈希表不存在,会自动创建一个哈希表 |
hget key field | 获取哈希表对应的field字段所关联的值。 |
hmget key field1 [field2…] | 获取哈希表对应的field1, field2…字段所关联的值。 |
hdel key field1 [field2…] | 删除哈希表对应的field1, field2..字段。 |
hsetnx key field value | 仅当field不存在时才添加field-value |
hkeys key | 查看哈希表所有的field |
hvals key | 查看哈希表所有的value |
hlen key | 获取哈希表有多少对field-value |
hexists key field | 查看field是否存在 |
hstrlen key field | 获取哈希表里field的值的长度 |
*哈希表: key对应的哈希表
1 |
|
2)value是数值的操作
命令 | 描述 |
---|---|
hincrby key field 整数 | 将key对应的哈希表的field字段的值添加指定数值。 |
hincrbyfloat key field 小数值 | 将key对应的哈希表的field字段的值添加指定小数值。 |
1 |
|
3、小结
一个拥有少量(100个左右)字段的hash需要 很少的空间来存储,所有你可以在一个小型的 Redis实例中存储上百万的对象。
尽管Hashes主要用来表示对象,但它们也能够存储许多元素,所以你也可以用Hashes来完成许多其他的任务。
一个hash最多可以包含2^32^-1 个key-value键值对(超过40亿)。
六、Redis Sets
1、集合简介
Redis集合是一个无序
的字符串合集。你可以以O(1) 的时间复杂度(无论集合中有多少元素时间复杂度都为常量)完成 添加,删除以及测试元素是否存在
的操作。
集合的特性:集合内的元素都是唯一的,向集合多次添加同一个元素时,集合只会保留一个元素,添加元素的前就可以不用判断元素是否存在。
2、集合基本操作
1)通用命令
命令 | 描述 |
---|---|
sadd key element [element …] | 添加一个或多个元素到集合内。 注:集合不存在时,会自动创建一个集合,并把元素添加进去 |
scard key | 获取集合内元素的数量。 |
smembers key | 获取集合内所有的元素。 |
srem key element [element…] | 在集合中删除一个或多个元素。 |
sismember key element | 查看集合中是否存在member元素。 |
smismember key element [element…] | 查看集合中是否存在一个或多个元素。 |
srandmember key [数量] | 随机查看指定数量的成员。 |
spop key [数量] | 随机删除指定数量的成员。 |
1 |
|
2)交集、并集以及差集
命令 | 描述 |
---|---|
smove key1 key2 element | 将集合1的指定元素移动到集合2。 |
sinter key1 [key2…] | 查看给定集合的交集。 注:多个集合交集,是两个集合先取交集,交集再跟后面的集合去交集。 |
sinterstore newkey key1 [key2…] | 将给定集合的交集创建为新的集合newkey。 |
sunion key1 [key2…] | 查看给定集合的并集。 |
sunionstore newkey key1 [key2…] | 将给定集合的并集创建为新的集合newkey。 |
sdiff key1 [key2…] | 查看给定集合的差集。 差集:集合1存在的,在集合2内不存在的元素。 |
sdiffstore newkey key1 [key2…] | 将给定集合的差集创建为新的集合newkey。 |
1 |
|
3、小结
Redis集合是一个无序的字符串合集。
集合可以高效的处理:
- 用集合跟踪一个独特的事。想要知道所有访问某个博客文章的独立IP?只要每次都用
sadd
来处理一个页面访问。那么你可以肯定重复的IP是不会插入的。 - Redis集合能很好的表示关系。你可以创建一个tagging系统,然后用集合来代表单个tag。接下来你可以用
sadd
添加命令把所有拥有tag的对象的所有ID添加进集合,这样来表示这个特定的tag。如果你想要同时有3个不同tag的所有对象的所有ID,那么你需要使用sinter
交集命令。 - 使用
spop
或者srandmember
命令随机地获取元素。 - 支持一些服务端的命令从现有的集合出发去进行集合运算。 所以你可以在很短的时间内完成合并(union),求交(intersection), 找出不同元素的操作。
七、Redis Sorted Sets
1、有序集合简介
有序集合与集合类似,不同的地方在于每个字符串元素都关联一个叫score
的浮动数值(floating number value)。里面的元素是按score进行排序,当多个字符串具有相同的score
时,这些字符串按字典序
排列。
使用有序集合,你可以非常快地(O(log(N)))完成添加,删除和更新元素
的操作。 因为元素是在插入时就排好序的,所以很快地通过分数(score)或者 位次(position)获得一个范围的元素。
访问有序集合的中间元素同样也是非常快的,因此你可以使用有序集合作为一个没有重复成员的优先队列
(c++里面的优先队列的概念)。 在这个列表中, 你可以轻易地访问任何你需要的东西: 有序的元素,快速的存在性测试,快速访问集合中间元素!
2、有序集合基本操作
1) 通用命令
命令 | 描述 |
---|---|
zadd key [NX | XX] [GT | LT] [CH] [INCR] score1 element [score2 element…] |
添加一个或多个元素,每个元素都有一个分数(score)用于排序。 NX:只有元素不存在的时候才添加 XX:只有元素存在时修改元素 LT(less than):只有在分数score低于原来元素的分数时才更新分数 GT(greater than):只有在分数score高于原来元素的分数时才更新分数 注:NX不可与GT\LT同时使用 CH(changed):返回变更的元素数量,默认返回新增的元素数量 INCR:累加分数 注:INCR只能操作一个分数-元素对 |
zrem key element [element…] | 删除有序集合内一个或多个元素。 |
zcount key left right | 获取在[left, right]区间内的元素数量。 注:默认闭区间,开区间在分数前加 ( 支持无穷大表示: inf 表示正无穷大,-inf 表示负无穷大 |
zscore key element | 查看有序集合内指定元素的分数。 注:元素不存在返回nil |
zmscore key element1 [element2…] | 查看有序集合内指定元素element1,element2…的分数。 |
zcard key | 查看有序集合内元素数量。 |
zincrby key 数值 element | 给有序集合内指定元素的分数增加指定数值。 |
1 |
|
2)区间操作
命令 | 描述 |
---|---|
zrange key left right [BYSCORE | BYLEX] [REV] [LIMIT 偏移量 查看数量] [WITHSCORES] |
查看分数在[left, right]区间内元素。 BYSCORE:按分数升序排列。 注:BYSCORE支持开区间,需要在分数前加 ( 支持无穷大表示: inf 表示正无穷大,-inf 表示负无穷大BYLEX:分数相同时,按照元素 字典序 排序注:BYLEX指定字符串区间要指定开闭区间:”[string”表示闭区间,”(string”表示开区间 BYLEX支持选取从开始到结束:”-“表示开始,”+”表示结束 REV(reverse):有序集合排序后反转。 LIMIT:用于指定查看的范围 注:仅在BYSCORE/BYLEX时可用 WITHSCORES:输出时元素与分数一起输出 |
zrangestore newkey key left right | 将有序集合[left, right]区间内的元素存储到newkey有序集合内。 注:类似zrange key left right BYSCORE | BYLEX] [REV] [LIMIT 偏移量 查看数量] |
zlexcount key startString endString | 查看有序集合内指定字符串区间的元素数量。 注:类似zrange key startString endString BYLEX |
zremrangebyscore key minScore maxScore | 删除有序集合内指定分数区间的所有元素。 注:类似zrange key minScore maxScore BYSCORE |
zrank key element | 查看有序集合内指定元素的升序排名。 注:排名从第0位开始 |
zrevrank key element | |
zremrangebyrank key startRank endRank | 删除有序集合内指定排名区间的所有元素。 注:排名从第0位开始,-n表示倒数第几名 |
1 |
|
3)交集、并集以及差集
命令 | 描述 |
---|---|
zinter key的数量 key1 [key2…] [weights 权重1 [权重2…] [aggregate sum | min | max] [withscores] |
查看给定的有序集合的交集。 werights:依次给每个集合的分数设置权重,默认权重为1 aggregate:新分数的计算方法,默认是sum 注:新分数=aggregate(集合1中该元素的分数 * 权重1+集合2中该元素的分数 * 权重2…) (符号是aggregate决定的可以是sum加,min取两者最小,max取两者最大) withscores:带分数显示 |
zinterstore newkey key的数量 key1 [key2…] [weights 权重1 [权重2…] [aggregate sum | min | max] |
将给定的有序集合的交集存储到新的有序集合newkey。 |
zunion key的数量 key1 [key2…] [weights 权重1 [权重2…] [aggregate sum | min | max] [withscores] |
查看给定的有序集合的并集。 |
zunionstore newkey key的数量 key1 [key2…] [weights 权重1 [权重2…] [aggregate sum | min | max] |
将给定的有序集合的并集存储到新的有序集合newkey。 |
zdiff key的数量 key1 [key2…] [withscores] | 查看给定的有序集合的差集。 |
zdiff newkey key的数量 key1 [key2…] | 将给定的有序集合的差集存储到新的有序集合newkey。 |
1 |
|
3、小结
使用有序集合你可以很好地完成很多在其他数据库中难以实现的任务。
有序集合可以:
- 在一个大型在线游戏中建立一个排行榜,每当有新的记录产生时,使用
ZADD
来更新它。你可以用ZRANGE
轻松地获取排名靠前的用户, 你也可以提供一个用户名,然后用ZRANK
获取他在排行榜中的名次。 同时使用ZRANK
和ZRANGE
你可以获得与指定用户有相同分数的用户名单。 所有这些操作都非常迅速。 - 有序集合通常用来索引存储在Redis中的数据。 例如:如果你有很多的hash来表示用户,那么你可以使用一个有序集合,这个集合的年龄字段用来当作评分,用户ID当作值。用·ZRANGEBYSCORE·可以简单快速地检索到给定年龄段的所有用户。
注意:
大多数有序集合操作是 O(log(n)),其中n是成员数。ZRANGE
在运行具有较大返回值(例如,数万条或更多)的命令时要小心。该命令的时间复杂度为 O(log(n) + m),其中m是返回的结果数。