Redis是一个key-value的数据库,key一般是string类型,不过value的类型多种多样:
- string《 hello world 》
- Hash《 {name: “jack”, age: 12} 》
- List 《 [A -> B -> C -> C] 》
- Set 《 {A, B, C} 》
- SortedSet 《 {A: 1, B: 2, C: 3} 》
- GEO 《 {A: (120.3, 30.5)} 》
- BitMap 《 01110101010101 》
- HyperLog《 01110101010101 》
还有更多,常见的是前面的五种,也叫基本类型。
Redis通用命令通用命令是不分数据类型的,都可以使用的命令,常见的有:
- KEYS 查看符合模板(pattern)的所有key
使用(返回所有的key,不建议在生产环境下使用)
查询所有的key
KEYS *
查询以a开头的key
KEYS a*
如果数据很多,别用这个,因为Redis是单线程,所以执行KEYS 的时候,会花很多时间,整个Redis服务被阻塞,其他的命令无法执行。
- DEL 删除一个指定的key
使用(可以删除一个或多个,返回删除的个数)
DEL name DEL name age
- EXISTS 判断key是否存在
使用(可以判断一个或多个,返回存在的个数)
EXISTS name EXISTS name age
-
EXPIRE:给一个key设置有效期(单位是秒),有效期到时该key会自动被删除
-
TTL:查看一个key的剩余有效期(被删除后,返回-2。返回-1,就代表永久有效。)
使用
EXPIRE name 20 TTL name
所以一般情况下,给Redis存入数据时,可能会建议设置有效期,不设置就永久了。
string类型字符串类型是Redis中最简单的存储类型。其value是字符串,不过根据字符串的格式不同,又可分为3类:
- string 普通字符串
- int 整数类型,可以做自增自减的操作
- float 浮点类型,可以做自增自减的操作
这三个不管是那种形式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型最大空间不能超过512M
string类型的常见命令如下:
- SET:添加或修改已经存在的一个string类型的键值对
set name rose
- GET:根据key获取string类型的value
get name
- MSET:批量添加多个string类型的键值对
MSET k1 v1 k2 v2
- MGET:根据多个key获取多个string类型的value
MGET k1 k2
- INCR:让一个整形的key自增1
INCR age
- INCRBY:让一个整形的key自增并指定步长,如incrby num 2 让num值自增2
INCRBY age 2 INCRBY age -1 #这样就能自减(也可以使用DNCR)
- INCRBYFLOAT:让一个浮点类型的数字自增并指定步长
set score 10.1 INCRBYFLOAT 0.5
-
SETNX:添加一个string类型的键值对,前提是这个key不存在,否则不执行。所以这个是只新增。和 set name asd nx 效果一样
-
SETEX:添加一个string类型的键值对,并且指定有效期,上面的EXPIRE是给已存在的设置有效期,这个是新添加时同时指定
SETEX name 10 zhangsan
这个和set name zhangsan ex 10 效果一样。
思考Redis没有类似MySQL中的table概念,我们该如何区分不同类型的key呢?例如需要存储用户、商品信息到Redis,有一个用户的id是1,有一个商品的id也恰好是1。
Redis的key允许有多个单词形成层级结构,多个单词之间用“:”隔开,比如格式如下:
项目名:业务名:类型:id
这个格式并非固定,也可以根据自己的需求删除或添加词条。
例如我们的项目名称叫xiangmu,有user和product两种不同类型的数据,我们可以如下定义key:
-
user相关的key :xiangmu:user:1
-
product相关的key:xiangmu:product:1
相应的value可能是Java对象,比如User对象,可以序列化成json字符串后存储,比如:
set xiangmu:user:1 {"id":1, "name":"asd", "age":21}
用这种方式时,在终端可能没啥感觉,但用客户端时,会看的很方便,比如会出现xiangmu包,里面有user包之类的…(客户端图省略)
hash类型hash类型,也叫散列,其value是一个无序字典,类似于Java中的hashmap结构。string结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段是很不方便。比如xiangmu:user:1 {“id”:1, “name”:“asd”, “age”:21},在这里面value是字符串,如果想单独修改里面的某个字段,是很难修改的。hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD。
hash类型的常见命令- HSET key field value:添加或修改hash类型key的field的值
HSET xiangmu:user:1 name asd HSET xiangmu:user:1 age 21
如果想单独修改age的话,执行HSET xiangmu:user:1 age 18
- HGET key field:获取一个hash类型key的field的值
HGET xiangmu:user:1 name
- HMSET:批量添加多个hash类型key的field的值,就是可以添加多个field value。
HMSET xiangmu:user:1 name asd age 21
- HMGET:批量获取多个hash类型key的多个field的值
HMGET xiangmu:user:1 name age
- HGETALL:获取一个hash类型的key中的所有的field和value
HGETALL xiangmu:user:1
- HKEYS:获取一个hash类型的key中的所有的field
HKEYS xiangmu:user:1
- HVALS:获取一个hash类型的key中的所有的value
HVALS xiangmu:user:1
- HINCRBY:让一个hash类型key的某个field的value自增并指定步长
HINCRBY xiangmu:user:1 age 2 HINCRBY xiangmu:user:1 age -2 #给负数就是负增长
- HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行。
HSETNX xiangmu:user:1 name asd #由于有name这个field,所以这次不执行,没有就执行。list类型
Redis中的list类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索,也可以支持反向检索。特征与LinkedList类似:
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一般
常用来存储有序数据,比如朋友圈点赞列表,评论列表等。list类型的常见命令:
- LPUSH key element…:向列表左侧(可以理解成队首)插入一个或多个元素
LPUSH key v1 v2 v3 # 由于是左侧插入,所以结果的顺序是v3 v2 v1
- LPOP key:移除并返回列表左侧的第一个元素,没有则返回nil
LPOP key LPOP key 2 #这是指取2个元素。由于取出来后会移除,所以总结果中v3 v2没了。
- RPUSH key element…:向列表右侧(可以理解成队尾)插入一个或多个元素
RPUSH key v4 v5 v6 #由于是右侧插入,所以结果的顺序是v4 v5 v6
-
RPOP key:移除并返回列表右侧的第一个元素,没有则返回nil
-
LRANGE key start end:返回一段角标范围内的所有元素
LRANGE key 1 2 #从左侧取从下标1开始到下标2
- BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil
格式:BLPOP key[key...] timeout(秒)
BLPOP k1 10 #这样的话,取k1这个key的左侧第一个元素,没有的话,等10秒。执行后,终端就阻塞状态。
在执行前,开新的终端,往k1里假如一个元素后,那个才会取出来并结束。BLPOP是阻塞式获取的意思。
思考1)如何利用list结构模拟一个栈?
栈的特点是先进后出,所以入口和出口在同一边。所以入可以用L[R]PUSH,出用L[R]POP即可。
2)如何利用list结构模拟一个队列?
队列的特点是先进先出,所以入口和出口不在同一边。可以用L存,R取。或R存,L取。
3)如何利用list结构模拟一个阻塞队列?
阻塞队列就是有元素就取,没有就等。因为是队列,所以要先保证入口出口不同边,出队时采用BLPOP或BRPOP。
redis的set结构与Java中的hashset类似,可以看做是一个value为null的hashmap。因为也是一个hash表,因此具备与hashset类似的特征:
- 无序
- 元素不可重复
- 查找快
- 支持交集、并集、差集等功能
set类型的常见命令:
- SADD key member…:向set中添加一个或多个元素
sadd k1 v1 v2 v3
- SREM key member…:移除set中的指定元素
SREM k1 v1
- SCARD key:返回set中元素的个数
SCARD k1
- SISMEMBER key member:判断一个元素是否存在set中
SISMEMBER k1 v1
- SMEMBERS:获取set中所有元素
SMEMBERS k1
[以上是对单个set的操作,下面开始是对多个set的操作命令]
-
SINTER k1 k2…:求k1和k2的交集。k1和k2共有的。
-
SDIFF k1 k2…:求k1和k2的差集。在k1里面有,但k2里没有的。
-
SUNIOn k1 k2…:求k1和k2的并集。k1和k2都搞一起,set是不能重复的,所以重复的元素变成1个。
将下列数据用Redis的set集合来存储:
- 张三的好友有:李四、王五、赵六。
sadd zs lisi wangwu zhaoliu
- 李四的好友有:王五、麻子、二狗。
sadd ls wangwu mazi ergou
利用set的命令实现下列功能:
- 计算张三好友有几人
SCARD zs
- 计算张三和李四有哪些共同好友
SINTER zs ls
- 查询哪些人是张三的好友却不是李四的好友
SDIFF zs ls
- 查询张三和李四的好友总共有哪些人
SUNIOn zs ls
- 判断李四是否是张三的好友
SISMEMBER zs lisi
- 判断张三是否是李四的好友
SISMEMBER ls zhangsan
- 将李四从张三的好友列表中移除
SREM zs lisiSortedSet类型
redis的sortedset是可排序的set集合,与Java中的treeset有些类似,但底层数据结构却差别很大。sortedset中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加hash表。sortedset具备下列特性:
- 可排序
- 元素不重复
- 查询速度快
因为sortedset的可排序特性,经常被用来实现牌行榜这样的功能。sortedset的常见命令有:
- ZADD key score member:添加一个或多个元素到sortedset,如果已经存在则更新其score值
- ZREM key member:删除sortedset中的一个指定元素
- ZSCORE key member:获取sortedset中的指定元素的score值
- ZRANK key member:获取sortedset中的指定元素的排名(排序默认是根据score来排的)
- ZCARD key:获取sortedset中的元素个数
- ZCOUNT key min max:统计score值在给定范围内的所有元素的个数(即这里的min max是分数值)
- ZINCRBY key increment member:让sortedset中的指定元素(分数的)自增,步长为指定的increment值
- ZRANGE key min max:按照score排序后(就会有排名了),获取指定排名范围内的元素(这里的min max不是分数值,而是排名)
- ZRANGEBYSCORE key min max:按照score排序后,获取指定score范围内的元素(这个是根据分数排名,所以min max是分数值)
- ZDIFF、ZINTER、ZUNIOn:求差集、交集、并集
注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可。REV代表reverse反转
案例:sortedset命令练习- 将班级的下列学生得分存入Redis的sortedset中:Jack 85,Lucy 89,rose 82,Tom 95,Jerry 78,Amy 92,miles 76
ZADD stus 85 Jack 89 Lucy 82 rose 95 Tom 78 Jerry 92 Amy 76 miles
添加之后,在客户端查看的话就会发现默认以分数的升序排序了。并实现下列功能:
- 删除Tom同学
ZREM stus Tom
-
获取Amy同学的分数
-
获取rose同学的排名
ZRANK stus rose #默认排名下,返回2,因为排名是0开始的,在默认的升序排名下,rose是第三位,所以是2 ZREVRANK stus rose #返回3,因为倒过来的话,rose的成绩是第四高,所以是3
- 查询80分以下有几个学生
ZCARD stus 查全部的学生数,这样的话返回6个人 ZCOUNT stus 0 80
- 给Amy同学加2分
ZINCRBY stus 2 Amy
- 查出成绩前3名的同学
ZRANGE stus 0 2 #由于默认是升序,所以0到2是等于分数倒数第三名,结果是miles Jerry rose ZREVRANGE stus 0 2 #由于默认是升序,所以倒序过来再查,结果是Amy Lucy Jack
- 查出成绩80分以下的所有同学
ZRANGEBYSCORE stus 0 80



