day02-Redis命令
Redis命令
1.Redis数据结构介绍
Redis是一个key-value的数据库,key一般是String类型,value的类型多种多样,value常见的八种类型:
Redis支持五种基本的数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set,有序集合)。
- 各个数据类型应用场景:
 
| 类型 | 简介 | 特性 | 场景 | 
|---|---|---|---|
| String(字符串) | 二进制安全 | 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M | --- | 
| Hash(字典) | 键值对集合,即编程语言中的Map类型 | 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去) | 存储、读取、修改用户属性 | 
| List(列表) | 链表(双向链表) | 增删快,提供了操作某一段元素的API | 1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列 | 
| Set(集合) | 哈希表实现,元素不重复 | 1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作 | 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐 | 
| Sorted Set(有序集合) | 将Set中的元素增加一个权重参数score,元素按score有序排列 | 数据插入集合时,已经进行天然排序 | 1、排行榜 2、带权重的消息队列 | 
不同的数据类型的操作会对应不同的命令,Redis为了方便我们学习,将操作不同数据类型的命令做了不同分组分组,在官网可以查看,也可以通过命令行查看:
2.Redis通用命令
通用指令是部分数据类型都可以使用的指令,常见的可以通过官方文档选择Generic分组查看:
或者使用命令行查看:help @generic
127.0.0.1:6379> help @generic
  DEL key [key ...]
  summary: Delete a key
  since: 1.0.0
  DUMP key
  summary: Return a serialized version of the value stored at the specified key.
  since: 2.6.0
  EXISTS key [key ...]
  summary: Determine if a key exists
  since: 1.0.0
  
  ....
这里介绍一些常见的通用命令:
- 
keys在本库中,查看符合输入模板的所有key的值:(不建议在生产环境上使用)#命令解释 127.0.0.1:6379> help keys #通过help [command] 可以查看一个命令的具体用法 KEYS pattern summary: Find all keys matching the given pattern since: 1.0.0 group: generic #例子 127.0.0.1:6379> keys * 1) "marry" 2) "jack" 127.0.0.1:6379> keys j* 1) "jack" - 
del删除一个或者多个key#命令解释 127.0.0.1:6379> help del DEL key [key ...] summary: Delete a key since: 1.0.0 group: generic #例子 127.0.0.1:6379> keys * 1) "foo" 2) "marry" 3) "jack" 4) "tom" 127.0.0.1:6379> del tom marry #一次可以删除多个key,返回的值是删除key的数量 (integer) 2 127.0.0.1:6379> keys * 1) "foo" 2) "jack" - 
exists判断一个或多个key是否存在#命令解释 127.0.0.1:6379> help exists EXISTS key [key ...] summary: Determine if a key exists since: 1.0.0 group: generic #例子 127.0.0.1:6379> exists jack foo tom mary #返回值是查询的key存在的个数 (integer) 2 - 
expire给一个key设置有效期,到期时该key自动删除#命令解释 127.0.0.1:6379> help expire EXPIRE key seconds summary: Set a key's time to live in seconds since: 1.0.0 group: generic #例子 127.0.0.1:6379> expire k1 5 #设置k1的过期时间为5秒 (integer) 1 127.0.0.1:6379> get k1 #5秒后查看,发现已经给被删除了 (nil) - 
ttl查看一个key的剩余有效期#命令解释 127.0.0.1:6379> help ttl TTL key summary: Get the time to live for a key since: 1.0.0 group: generic #例子 127.0.0.1:6379> ttl foo (integer) -1 #-1 代表该key为永久有效 127.0.0.1:6379> expire foo 5 (integer) 1 127.0.0.1:6379> ttl foo (integer) 2 #其他数字代表该key剩余时间(秒) 127.0.0.1:6379> ttl foo (integer) -2 #-2 代表该key已经过期 
3.String类型
string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
根据字符串的格式不同,又可以分为3类:
- 
String:普通字符串
 - 
int:整数类型,可以做自增、自减操作
 - 
float:浮点类型,可以做自增、自减操作
 
不管是哪种格式,底层都是字节数组形式存储,只不过是编码形式不同
- String类型常见命令
- set 添加或者修改已经存在的一个String类型的键值对
 - get 根据key获取String类型的value
 - mset 批量添加多个String类型的键值对
 - mget 根据多个key获取多个String类型的value
 - incr 让一个整型的value自增1
 - incrby 让一个整型的value自增并指定步长,例如 incrby num 2 #让key为num对应的value自增2
 - incrbyfloat 让一个浮点类型的数字自增并指定步长
 - setnx 添加一个String类型的键值对,前提是这个key不存在,否则不执行
 - setex 添加一个String类型的键值对,并且指定有效期
 
 
3.1key的层级格式
Redis没有类似MySQL的Table的概念,我们该如何区分不同类型的key呢?例如,需要存储用户、商品信息到redis,有一个用户id为1,有一个商品的id也恰好是1。
Redis的key允许有多个单词形成层级结构,多个单词之间用:隔开,例如:项目名:业务名:类型:id。由此我们可以根据层级关系来解决上面的问题:
user相关的key:项目名:user:1
product相关的key:项目名:product:1
如果value是一个Java对象,例如一个User对象,则可以将对象序列化为JSON字符串后存储,例如:
127.0.0.1:6379> set olien:user:1 '{"id":1, "name":"Jack", "age": 21}'
OK
127.0.0.1:6379> set olien:user:2 '{"id":2, "name":"Rose", "age": 18}'
OK
127.0.0.1:6379> set olien:product:1 '{"id":1, "name":"小米11", "price": 4999}'
OK
127.0.0.1:6379> set olien:product:2 '{"id":2, "name":"荣耀6", "price": 2999}'
OK
127.0.0.1:6379> keys olien*
1) "olien:product:1"
2) "olien:product:2"
3) "olien:user:1"
4) "olien:user:2"
127.0.0.1:6379>
我们在可视化软件查看,可以看到使用冒号隔开时,数据自然形成了不同的层级结构,这就可以避免id相同时的冲突,实现分层存储。
4.Hash类型
Hash 类型,也叫散列,其 value 是一个无需字典,类似 Java 中的 hashmap 结构。
Redis hash 是一个键值(key=>value)对集合。Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。每个 hash 可以存储 2^32 -1 键值对(40多亿)。
String结构是将对象序列化为json字符串后存储,但当需要修改对象的某个字段时很不方便:
而Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD操作:
- 
Hash常见的命令
这里的哈希表指的是一个hash类型(key-value[field-value])
- 
HSET key field value[field2 value2...]将哈希表 key 中的字段 field 的值设为 value127.0.0.1:6379> HSET lucy id 2 age 10 (integer) 2 - 
HGET key field获取存储在哈希表中指定字段的值 - 
HDEL key field [field2...]删除一个或者多个哈希表key的字段127.0.0.1:6379> HDEL lucy addr age (integer) 2 - 
HMSET key field1 [field2...]同时将多个field-value(域-值)对设置到哈希表key中127.0.0.1:6379> hmset lucy name lucy id 5 age 18 OK - 
HMGET key field1 [field2...]获哈希表中给定字段的值127.0.0.1:6379> HMGET lucy id age name 1) "5" 2) "18" 3) "lucy" - 
HGETALL key获取一个hash类型的key中的所有field和所有value127.0.0.1:6379> HGETALL lucy 1) "name" 2) "lucy" 3) "id" 4) "5" 5) "age" 6) "18" - 
HKEYS key获取哈希表key中的所有field127.0.0.1:6379> hkeys lucy 1) "name" 2) "id" 3) "age" - 
HLEN key获取哈希表key中所有字段的数量127.0.0.1:6379> HLEN lucy (integer) 4 - 
HVALS key获取哈希表key中的所有value127.0.0.1:6379> hvals lucy 1) "lucy" 2) "5" 3) "18" - 
HINCRBY key field increment为哈希表key中的指定字段的整数值加上增量increment127.0.0.1:6379> HINCRBY lucy age 100 (integer) 118 - 
HINCRBYFLOAT key field increment为哈希表key中的指定字段的浮点数值加上增量increment127.0.0.1:6379> HINCRBYFLOAT lucy score 30 "90" - 
HSETNX key field value只有在字段不存在时,设置哈希表key中字段的值127.0.0.1:6379> HSETNX lucy age 10086 (integer) 0 127.0.0.1:6379> HSETNX lucy addr beijing (integer) 1 - 
HEXISTS key field查看哈希表key中,指定的字段是否存在127.0.0.1:6379> HEXISTS lucy age #返回值1表示存在,0表示不存在 (integer) 1 127.0.0.1:6379> HEXISTS lucy foo (integer) 0 - 
HSCAN key cursor [MATCH pattern] [COUNT count]迭代哈希表中的键值对 
 - 
 
5.List类型
List 是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
Redis 的 List类型与 Java 的LinkedList 类似,可以看做是一个双向链表结构,可以同时支持正向检索和反向检索。
特征也和 LinkedList 类似:
- 有序
 - 元素可以重复
 - 插入和删除速度快
 - 查询速度一般
 
常用来存储一个有序数据,例如朋友圈点赞列表,评论列表等。
下表列出了列表相关的基本命令:
命令首字符:R代表列表右侧(Right),L代表列表左侧(Left)
| 命令及描述 | 
|---|
| BLPOP key1 [key2 ] timeout 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 | 
| BRPOP key1 [key2] timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 | 
| BRPOPLPUSH source destination timeout 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 | 
| LINDEX key index 通过索引获取列表中的元素 | 
| LINSERT key BEFORE|AFTER pivot value 在列表的元素前或者后插入元素 | 
| LLEN key 获取列表长度 | 
| LPOP key 移出并获取列表的第一个元素 | 
| LPUSH key value1 [value2] 将一个或多个值插入到列表头部 | 
| LPUSHX key value 将一个值插入到已存在的列表头部 | 
| LRANGE key start stop 获取列表指定范围内的元素 | 
| LREM key count value 移除列表元素 | 
| LSET key index value 通过索引设置列表元素的值 | 
| LTRIM key start stop 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。 | 
| RPOP key 移除列表的最后一个元素,返回值为移除的元素。 | 
| RPOPLPUSH source destination 移除列表的最后一个元素,并将该元素添加到另一个列表并返回 | 
| RPUSH key value1 [value2] 在列表中添加一个或多个值到列表尾部 | 
| RPUSHX key value 为已存在的列表添加值 | 
- 思考:使用List类型模拟 栈 / 队列 / 阻塞队列
 
根据上面的命令,我们就可以使用List类型模拟栈、队列、阻塞队列:
- 
模拟栈:只需要入口和出口在同一边
 - 
模拟队列:入口和出口在不同边
 - 
模拟阻塞队列:入口和出口在不同边,出队时采用 BLPOP 或 BRPOP
 
6.Set类型
Redis 的 Set 是 string 类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)
注意:如果在无序集合中的同一个元素被添加了两次,根据集合内元素的唯一性,第二次插入的元素将被忽略。集合中最大的成员数为 2^32 - 1(4294967295, 每个集合可存储40多亿个成员)。
Redis 的 Set 结构与 Java 中的 HashSet 类似,可以看做是一个 value为 null 的 HashMap。因为也是一个哈希表,因此具备与 HashSet 类似的特征:
- 无序
 - 元素不可重复
 - 查找快
 - 支持交集、并集、差集等功能
 
下表列出了 Redis 集合基本命令:
| 序号 | 命令及描述 | 
|---|---|
| 1 | SADD key member1 [member2] 向集合添加一个或多个成员 | 
| 2 | SCARD key 获取集合的成员数 | 
| 3 | SDIFF key1 [key2] 返回第一个集合与其他集合之间的差异。 | 
| 4 | SDIFFSTORE destination key1 [key2] 返回给定所有集合的差集并存储在 destination 中 | 
| 5 | SINTER key1 [key2] 返回给定所有集合的交集 | 
| 6 | SINTERSTORE destination key1 [key2] 返回给定所有集合的交集并存储在 destination 中 | 
| 7 | SISMEMBER key member 判断 member 元素是否是集合 key 的成员 | 
| 8 | SMEMBERS key 返回集合中的所有成员 | 
| 9 | SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合 | 
| 10 | SPOP key 移除并返回集合中的一个随机元素 | 
| 11 | SRANDMEMBER key [count] 返回集合中一个或多个随机数 | 
| 12 | SREM key member1 [member2] 移除集合中一个或多个成员 | 
| 13 | SUNION key1 [key2] 返回所有给定集合的并集 | 
| 14 | SUNIONSTORE destination key1 [key2] 所有给定集合的并集存储在 destination 集合中 | 
| 15 | SSCAN key cursor [MATCH pattern] [COUNT count] 迭代集合中的元素 | 
Set命令练习:
- 
将下列数据用redis的set集合来存储:
- 张三的好友有:李四,王五,赵六
 - 李四的好友有:王五,麻子,二狗
 
127.0.0.1:6379> sadd zs ls wu zl (integer) 3 127.0.0.1:6379> sadd ls wu mz eg (integer) 3 - 
利用Set命令来实现下列功能:
- 
计算张三的好友有多少人
127.0.0.1:6379> SCARD zs (integer) 3 - 
计算张三和李四有哪些共同好友
127.0.0.1:6379> SINTER zs ls #交集 1) "wu" - 
查询哪些人是张三的好友却不是李四的好友
127.0.0.1:6379> SDIFF zs ls #差集 1) "zl" 2) "ls" - 
查询张三和李四的好友总共有哪些人
127.0.0.1:6379> SUNION zs ls #并集 1) "wu" 2) "zl" 3) "eg" 4) "ls" 5) "mz" - 
判断李四是否是张三的好友
127.0.0.1:6379> SISMEMBER zs ls (integer) 1 - 
判断张三是否是李四的好友
127.0.0.1:6379> SISMEMBER ls zs (integer) 0 - 
将李四从张三的好友列表中删除
127.0.0.1:6379> SREM zs ls (integer) 1 
 - 
 
7.zset(SortedSet)类型
Redis 的 Sorted Set 是一个可排序的 Set集合,与 Java 中的 TreeSet 有些类似,但底层数据结构却差别很大。SortedSet 中的每一个元素都带有一个 score 属性(double类型),redis正是通过score来为集合中的成员进行从小到大的排序,底层的实现是一个跳表(SkipList)加哈希表。zset的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
SortedSet具备下列特性:
- 可排序
 - 元素不重复
 - 查询速度快
 
SortedSet常用于实现排行榜或者带权重的消息队列这样的功能。
下表列出了 redis 有序集合的基本命令:
注意:所有排名默认是升序,如果要降序则在命令的Z后面添加REV即可
SortedSet命令练习:
将班级的下列学生得分存入Redis的SortedSet中:
Jack 85,Lucy 89,Rose 82,Tom 95,Jerry 78,Amy 92,Miles 76
127.0.0.1:6379> ZADD student 85 jack 89 lucy 82 rose 95 tom 78 jerry 92 amy 76 miles
(integer) 7
并实现如下功能:
- 
删除Tom
127.0.0.1:6379> ZREM student tom (integer) 1 - 
获取Amy的分数
127.0.0.1:6379> ZSCORE student amy "92" - 
获取Rose的排名
127.0.0.1:6379> ZREVRANK student rose (integer) 3 #降序,从0开始,实际排名为4 - 
查询80分以下有几个学生
127.0.0.1:6379> ZCOUNT student 0 80 (integer) 2 - 
给Amy加2分
127.0.0.1:6379> ZINCRBY student 2 amy "94" - 
查询成绩前3名的同学
127.0.0.1:6379> ZREVRANGE student 0 2 1) "amy" 2) "lucy" 3) "jack" - 
查出80分以下的所有学生
127.0.0.1:6379> ZREVRANGEBYSCORE student 80 0 1) "jerry" 2) "miles"