Redis的数据结构
Redis的数据结构
redis是一种高级的key-value的存储系统,其中value支持五种数据类型。
- 字符串(String)
 - 哈希(hash)
 - 字符串列表(list)
 - 字符串集合(set)
 - 有序字符串集合(sorted set)
 
1. 存储字符串String
字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据,如JPEG图像数据或json对象描述信息等。在Redis中字符串类型的value最多可以容纳的数据长度是512M。

以下是常用命令:
- 赋值
设定key持有指定的字符串value,如果该key存在则进行覆盖操作。总是返回OK。 
[root@itzhouq32 bin]# ./redis-cli
127.0.0.1:6379> set username tom
OK
- 取值
获取key的value。如果与该key关联的value不是String类型,redis将返回错误信息,因为get命令只能用于获取String value;如果key不存在,返回nil。 
127.0.0.1:6379> get username
"tom"
127.0.0.1:6379> get xxx
(nil)
- 先取值再赋值
getset key value :先获取该key的值,然后再设置该key的值。 
127.0.0.1:6379> getset username jack
"tom"
127.0.0.1:6379> get username
"jack"
127.0.0.1:6379>
- 删除
del key :删除指定key 
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> del age
(integer) 1
127.0.0.1:6379> get age
(nil)
127.0.0.1:6379>
- 数值增减
incr key : 将指定的key的value原子性的增加1。如果该key不存在,其初始值为0。在incr之后其值为1.如果value的值不能转成整型,该操作将执行失败并返回相应的错误信息。 
127.0.0.1:6379> incr num
(integer) 1
127.0.0.1:6379> get num
"1"
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> get num
"2"
127.0.0.1:6379> incr hello
(integer) 1
127.0.0.1:6379> get hello
"1"
127.0.0.1:6379> set world china
OK
127.0.0.1:6379> incr world
(error) ERR value is not an integer or out of range
decr key : 将指定的key的value原子性的递减1.如果该key不存在,其初始值为0,在incr之后其值为-1.如果value的值不能转成整型,该操作将执行失败并返回相应的错误信息。
127.0.0.1:6379> decr num2
(integer) -1
127.0.0.1:6379> get num2
"-1"
incrby increment : 将指定的key的value原子性的增加increment。如果key不存在,其初始值为0.如果该值不能转化为整型,报错。
127.0.0.1:6379> incrby date 10
(integer) 10
127.0.0.1:6379> get date
"10"
decrby decrement :将指定的值原子性减少。
127.0.0.1:6379> decrby day 5
(integer) -5
127.0.0.1:6379> get day
"-5"
- 拼接字符串
append key value : 拼接字符串。如果key存在,则在原有的基础上追加该值;如果该key不存在,则重新创建一个key/value。返回值为字符串的长度。 
127.0.0.1:6379> append username 123
(integer) 7
127.0.0.1:6379> get username
"jack123"
127.0.0.1:6379> append yyy 123
(integer) 3
127.0.0.1:6379> get yyy
"123"
2. 存储Hash
Redis中的Hash类型可以看成具有String key 和String value的map容器。所以该类型非常适合于存储对象的信息。如Username、password和age。如果Hash中包含少量的字段,那么该类型的数据也将仅占用很少的磁盘空间。

常用命令:
- 赋值
hset key field value : 为指定的key设定field/value对(键值对)。
hmset key field value [field2 value2 ......] : 设置key中多个field/value。 
127.0.0.1:6379> hset myhash username jack
(integer) 1
127.0.0.1:6379> hset myhash age 18
(integer) 1
127.0.0.1:6379> hmset myhash2 username rose age 21
OK
- 取值
hget key field : 返回指定key中的field的值
hmget key field : 获取key中的多个field的值
hgetall key : 获取key中所有的field-value 
127.0.0.1:6379> hget myhash username
"jack"
127.0.0.1:6379> hmget myhash username age
1) "jack"
2) "18"
127.0.0.1:6379> hgetall myhash
1) "username"
2) "jack"
3) "age"
4) "18"
- 删除
hdel key field [field ...] : 可以删除一个或者多个字段,返回值是被删除的字段的个数。
del key : 删除整个hash 
127.0.0.1:6379> hgetall myhash2
1) "username"
2) "rose"
3) "age"
4) "21"
127.0.0.1:6379> hdel myhash2 username age
(integer) 2
127.0.0.1:6379> hgetall myhash2
(empty list or set)
127.0.0.1:6379> hmset myhash3 username marry age 20 addr shanghai
OK
127.0.0.1:6379> hgetall myhash3
1) "username"
2) "marry"
3) "age"
4) "20"
5) "addr"
6) "shanghai"
127.0.0.1:6379> del myhash3
(integer) 1
127.0.0.1:6379> hgetall myhash3
(empty list or set)
- 增加数字
hincrby key field increment : 设置key中field的值增加increment。 
127.0.0.1:6379> hget myhash age
"18"
127.0.0.1:6379> hincrby myhash age 5
(integer) 23
127.0.0.1:6379> hget myhash age
"23"
127.0.0.1:6379> hincrby myhash age -10
(integer) 13
127.0.0.1:6379> hget myhash age
"13"
- 判断
hexists key field : 判断指定的key中的field是否存在 
127.0.0.1:6379> hexists myhash password
(integer) 0
127.0.0.1:6379> hexists myhash username
(integer) 1
- 获取key所包含的field的数量
 
127.0.0.1:6379> hgetall myhash
1) "username"
2) "jack"
3) "age"
4) "13"
127.0.0.1:6379> hlen myhash
(integer) 2
- 获取所有的ekey
hkey key 
127.0.0.1:6379> hkeys myhash
1) "username"
2) "age"
- 获取所有的value
 
127.0.0.1:6379> hvals myhash
1) "jack"
2) "13"
3. 存储List类型
在Redis中,List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表 一样,我们可以在其头部(left)和尾部(right)添加新的元素。在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。

从元素插入和删除的效率视角来看,如果我们是在链表的两头插入或删除元素,这将会是非常高效的操作,即使链表中已经存储了百万条记录,该操作也可以在常量时间内完成。然而需要说明的是,如果元素插入或删除操作是作用于链表中间,那将会是非常低效的。相信对于有良好数据结构基础的开发者而言,这一点并不难理解。
ArrayList使用数组的方式存储数据,所以根据索引查询数据速度快,而新增或者删除元素时,涉及到位移操作,所以比较慢。
LinkedList使用双向链表,每一个元素都记录前后元素的指针,所以插入、删除数据时只是更改前后元素的指针指向即可,速度非常快。然后通过记录下标查询元素时需要从头开始索引,所以比较慢。
以下为常用命令:
- 查看列表
lrange key start end : 获取链表中从start到end的元素的值,start、end从0开始计数;也可以为负数,若为-1则表示链表尾部的元素。 
127.0.0.1:6379> lrange mylist 0 -1
1) "c"
2) "b"
3) "a"

两端添加
lpush key value [value1 value2]... : 在指定的key所关联的list的头部插入所有的values,如果该key不存在,该命令在插入前创建一个与该key关联的空链表,之后再向链表的头部插入数据。插入成功,返回元素的个数。rpush key value [value1 value2]... : 在该list的尾部添加元素。
127.0.0.1:6379> lpush mylist2 a b c d
(integer) 4
127.0.0.1:6379> rpush mylist2 1 2 3
(integer) 7
127.0.0.1:6379> lrange mylist2 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "1"
6) "2"
7) "3"

- 两端弹出
lpop key : 返回并弹出指定key关联得链表中得第一个元素,即头部元素。如果该key不存在,返回nil。
rpop key : 从尾部弹出元素。 
127.0.0.1:6379> lpop mylist2
"d"
127.0.0.1:6379> lrange mylist2 0 -1
1) "c"
2) "b"
3) "a"
4) "1"
5) "2"
6) "3"
127.0.0.1:6379> rpop mylist2
"3"
127.0.0.1:6379> lrange mylist2 0 -1
1) "c"
2) "b"
3) "a"
4) "1"
5) "2"
4. 存储set类型
在redis中,可以将Set类型看作是没有排序的字符集合,和List类型一样,我们也可以在该类型的数值上执行添加、删除和判断某一元素是否存在等操作。这些操作的时间复杂度为O(1),即常量时间内完成依次操作。
和List类型不同的是,Set集合中不允许出现重复的元素。
常用命令:
- 增加/删除元素
sadd key values[ value1 value2...] : 向set中添加数据,如果key的值已经存在则不会重复添加。
srem key members[member1 member2...] : 删除set中指定的成员 
127.0.0.1:6379> sadd myset a b c
(integer) 3
127.0.0.1:6379> srem myset 1 2
(integer) 0
127.0.0.1:6379> srem myset a b
(integer) 2
- 获得集合的元素
smembers key : 获取set中所有的成员
sismember key member:判断参数指定的成员是否在该set中,1表示存在,0表示不存在,或者该key本身不存在。 
127.0.0.1:6379> smembers myset
1) "c"
127.0.0.1:6379> sismember myset a
(integer) 0
127.0.0.1:6379> sismember myset c
(integer) 1
- 集合的差集运算
sdiff key1 key2...:返回key1与key2中相差的成员,而且与key的顺序有关,即返回差集。 
127.0.0.1:6379> sadd mya1 a b c
(integer) 3
127.0.0.1:6379> sadd myb1 a c 1 2
(integer) 4
127.0.0.1:6379> sdiff mya1 myb1
1) "b"
- 集合的交集运算
sinter key1 key2 key3 : 返回交集 
127.0.0.1:6379> smembers mya1
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> smembers myb1
1) "a"
2) "1"
3) "2"
4) "c"
127.0.0.1:6379> sinter mya1 myb1
1) "a"
2) "c"
- 集合的并集运算
sunion key1 key2 key3 ....:返回并集 
127.0.0.1:6379> sunion mya1 myb1
1) "1"
2) "b"
3) "c"
4) "a"
5) "2"
- set的使用场景
可以使用Redis的set数据类型跟踪一些唯一性数据,比如访问某一个博客的唯一IP地址信息。对于此场景,我们仅需在每次访问该博客时将访问者的IP存入redis中,set集合类型会自动保证IP地址的唯一性。 
充分利用Set类型的服务端聚合操作方便、高效的特性,可以用于维护数据对象之间的关联关系。比如所有购买某一电子设备的客户ID被存储在一个特定的set中,而购买另一种电子产品的客户ID被存储在另外一个set中,如果此时我们想获取有哪些客户同时购买了这两种商品时,set的一些命令可以充分发挥优势了。
5. 存储sortedset类型
sortedset和set极为相似,他们都是字符串的集合,都不允许重复的成员出现在一个set中。他们之间的主要差别是sortedset中每一个成员都会有一个分数与之关联。redis正是通过分数来为集合的成员进行从小到大的排序。sortedset中分数是可以重复的。
常见命令:
- 添加元素
zadd key score member score2 member2...:将成员以及该成员的分数存放到sortedset中。如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入到集合的元素的个数,不包含之前已经存在的元素。 
127.0.0.1:6379> zadd mysort 70 zhangsan 80 lisi 60 wangwu
(integer) 3
127.0.0.1:6379> zadd mysort 100 zhangsan
(integer) 0
- 获取元素
zscore key member :返回指定成员的分数 
127.0.0.1:6379> zscore mysort zhangsan
"100"
zcard key : 获取集合中成员数量
127.0.0.1:6379> zcard mysort
(integer) 3
- 删除元素
zrem key member [member...] : 移除集合中指定的成员,可以指定多个成员 
127.0.0.1:6379> zrem mysort wangwu lisi
(integer) 2
- 范围查询
zrange key start end [withscores] : 获取集合中脚注为start-end的成员,[withscores]参数表明返回的成员包含其分数。 
27.0.0.1:6379> zadd mysort 20 qianqi 89 zhaoba
(integer) 2
127.0.0.1:6379> zadd mysort 50 jack 98 rose
(integer) 2
127.0.0.1:6379> zrange mysort 0 -1
1) "qianqi"
2) "jack"
3) "zhaoba"
4) "rose"
5) "zhangsan"
127.0.0.1:6379> zrange mysort 0 -1 withscores
 1) "qianqi"
 2) "20"
 3) "jack"
 4) "50"
 5) "zhaoba"
 6) "89"
 7) "rose"
 8) "98"
 9) "zhangsan"
10) "100"
zrevrange key start stop [withscores] : 按照分数从大到小的顺序返回索引从start到stop之间的所有元素(包含两端的元素)。
127.0.0.1:6379> zrevrange mysort 0 -1 withscores
 1) "zhangsan"
 2) "100"
 3) "rose"
 4) "98"
 5) "zhaoba"
 6) "89"
 7) "jack"
 8) "50"
 9) "qianqi"
10) "20"
zremrangebyrank key start stop : 按照排名范围删除元素
127.0.0.1:6379> zremrangebyrank mysort 0 4
(integer) 5
- 使用场景
可以用于一个大型在线游戏的积分排行榜。每当玩家的分数发生变化时,可以执行zadd命令更改新玩家的分数,此后再通过zrange命令获取积分top10的用户信息。 
sortedset类型还可以用于构建索引数据。
Redis的数据结构的更多相关文章
- Redis基本数据结构总结之STRING和LIST
		
Redis基本数据结构总结前言 Redis的特点在于其读写速度特别快,因为是存储在内存中的,其非常适合于处理大数据量的情况:还有一个是其不同于其他的关系型数据库,Redis是非关系型数据库,也就是我们 ...
 - Redis基本数据结构总结之SET、ZSET和HASH
		
Redis基本数据结构总结 前言 Redis的特点在于其读写速度特别快,因为是存储在内存中的,其非常适合于处理大数据量的情况:还有一个是其不同于其他的关系型数据库,Redis是非关系型数据库,也就是我 ...
 - Redis各种数据结构性能数据对比和性能优化实践
		
很对不起大家,又是一篇乱序的文章,但是满满的干货,来源于实践,相信大家会有所收获.里面穿插一些感悟和生活故事,可以忽略不看.不过听大家普遍的反馈说这是其中最喜欢看的部分,好吧,就当学习之后轻松一下. ...
 - 聊一聊Redis的数据结构
		
如果没有记错的话,应该是在两个月前把 我们经常看到此类的文章: Redis的五种数据结构 Redis的数据结构以及对应的使用场景 其实以数据结构这个词去说明Redis的String.Hash.List ...
 - Redis学习——数据结构介绍(四)
		
一.简介 作为一款key-value 的NoSQL数据库,Redis支持的数据结构比较丰富,有:String(字符串) .List(列表) .Set(集合) .Hash(哈希) .Zset(有序集合) ...
 - Redis常用数据结构
		
Redis常用数据结构包括字符串(strings),列表(lists),哈希(hashes),集合(sets),有序集合(sorted sets). redis的key最大不能超过512M,可通过re ...
 - Redis的数据结构、通用操作及其特性
		
Redis的数据结构 五种数据类型: 字符串(String).字符串列表(list).字符串集合(set).有序字符串集合(sorted set).哈希(hash) key定义的注意点: 不要过长,不 ...
 - Redis学习笔记之Redis基本数据结构
		
Redis基础数据结构 Redis有5种基本数据结构:String(字符串).list(列表).set(集合).hash(哈希).zset(有序集合) 字符串string 字符串类型是Redis的va ...
 - 你真的懂redis的数据结构了吗?redis内部数据结构和外部数据结构揭秘
		
Redis有哪些数据结构? 字符串String.字典Hash.列表List.集合Set.有序集合SortedSet. 很多人面试时都遇到过这种场景吧? 其实除了上面的几种常见数据结构,还需要加上数据结 ...
 
随机推荐
- my eclipse 端口号被占用问题 Mac上
			
首先在终端输入 lsof -i :8080 (8080是端口号) 找到进程之后 在终端杀死进程 kill -9 7934 重新运行
 - 背水一战 Windows 10 (121) - 后台任务: 推送通知
			
[源码下载] 背水一战 Windows 10 (121) - 后台任务: 推送通知 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 推送通知 示例演示如何接收推送通知/WebA ...
 - Dubbo 源码分析 - 自适应拓展原理
			
1.原理 我在上一篇文章中分析了 Dubbo 的 SPI 机制,Dubbo SPI 是 Dubbo 框架的核心.Dubbo 中的很多拓展都是通过 SPI 机制进行加载的,比如 Protocol.Clu ...
 - 工作jQuery基础复习(一)
			
1.prop() 方法 设置或者返回被选元素的属性和值 当该方法用于返回属性值时,则返回第一个匹配元素的值 当该方法设定属性值时,则为匹配元素集合设置一个或者多个属性/值对
 - 通过Weeman+Ettercap配合拿下路由器管理权限
			
通过Weeman+Ettercap配合拿下路由器管理权限 本文转自>>>i春秋学院 本篇文章主要介绍如何在接入无线网络后如何拿到路由器的管理权限,至于如何得到路由器连接密码可以参考 ...
 - java数据结构面试问题—快慢指针问题
			
上次我们学习了环形链表的数据结构,那么接下来我们来一起看看下面的问题, 判断一个单向链表是否是环形链表? 看到这个问题,有人就提出了进行遍历链表,记住第一元素,当我们遍历后元素再次出现则是说明是环形链 ...
 - C 线性表的顺序存储实现及插入、删除等操作示例
			
一.线性表的定义 线性表(Linear List)是由同一类型元素构成的有序序列的线性结构.线性表中元素的个数称为线性表的长度:线性表内没有元素(长度为0)时,称为空表:表的起始位置称为表头,表的结束 ...
 - a标签一个有利于SEO的属性rel="nofollow"
			
最近想了解学些一下SEO,然后看了一些基础的视频,视频里提到了a标签的rel="nofollow"属性. 说来惭愧,第一次看到这个属性,都不知道这个属性是干嘛的 nofollow是 ...
 - editormd实现文章详情页面预览
			
继之前博客写了editmd.js(国内开源的一款前端Markdown框架)实现的写文章功能之后,本博客介绍使用editormd实现文章预览功能,之前博客链接:https://blog.csdn.net ...
 - 机器学习入门10 - 正则化:简单性(Regularization for Simplicity)
			
原文链接:https://developers.google.com/machine-learning/crash-course/regularization-for-simplicity 正则化指的 ...