索引
redis数据类型及简单命令
redis的数据类型有字符串(String)、列表(Lists)、集合(Sets)、有序集合(Sorted sets)、哈希(hashes)、比特(bit)、HyperLogLogs;
先说一下redis的keys,redis的键是一个字符串,即使是空字符串也可以作为有效key值。键值不建议太长,不仅消耗内存,而且查找计算的成本比较高。也不建议太短,例如键值 u:3892:p ,虽然很短,但不易阅读,可以使用 user:3892:password,即方便阅读,也不会占用太多内存。建议实际开发中坚持使用一种风格的键值。
Strings(字符串)
最简单的Redis数据类型。
存取操作:set、get
# set命令 存
> set name:1 Jack
OK
# get命令 取
> get name:1
Jack
判断 + 存操作:nx、xx
# nx参数 当键值不存在时存储,否则存储失败
> set name:1 Jack nx
(nil)
> set name:2 Tom nx
OK
# xx参数 当键值存在时存储,否则存储失败
> set name:2 Bob xx
OK
> set name:3 Bob xx
(nil)
原子递增/减操作:incr、incrby / decr、decrby
命令:递增 incr/incrby 递减 decr/decrby
注意:使用以上命令时若键值不存在,则默认键值初始值为0,再执行递增/递减操作
# 设置键user:196:look.good.num初始值为1
> set num:1 1
OK
> get num:1
"1"
# incr命令 将字符串解析为整型,将其加一
> incr num:1
(integer) 2
> get num:1
"2"
# incrby命令 设置递增增量
> incrby num:1 10
(integer) 12
> get num:2
"12"
批量存储/获取:mset、mget
# mset批量存储多个键值对
> mset num:2 10 num:3 20 num:4 30
OK
# mget批量获取多个键值对
> mget num:2 num:3 num:4
1) "10"
2) "20"
3) "30"
修改、删除或查询键存在:exists、type、del、
# exists命令判断键num:4是否存在
> exists num:4
(integer) 1
# type命令判断键num:4值的类型
> type num:4
string
# del命令删除键值num:4
> del num:4
(integer) 1
> exists num:4
(integer) 0
数据过期时间:expire、ex、ttl
可以使用
expire
命令设置过期时间,也可以在存储时设置过期时间。
ttl
命令查看当前剩余存活时间
> set num:4 10
OK
# 第一种:设置num:4过期时间为20秒
> expire num:4 20
(integer) 1
# 第二种:设置num:4过期时间为20秒
> set num:4 10 ex 20
OK
# 过期前查询
> get num:4
"10"
# 查询剩余存活时间
> ttl num:4
(integer) 14
# 过期后查询
> get num:4
(nil)
Lists(列表)
队列的存取:lpush、rpush、lrange、lpop、rpop、llen
lpush、rpush
都可以同时推入多个元素
lrange
根据下表索引获取元素,0是第一个元素,依次往下;索引为负数表示从尾部计数,-1表示最后一个,-2表示倒数第二个。
lpop、rpop
从列表中推出一个元素
llen
队列的长度
# 从队列左边推入一个元素
> lpush mylist A
(integer) 1
# 从队列右边推入一个元素
> rpush mylist B
(integer) 2
> rpush mylist C D E F
(integer) 6
# 获取第一个到最后一个所有元素
> lrange mylist 0 -1
1) "A"
2) "B"
3) "C"
4) "D"
5) "E"
6) "F"
# 从左边推出一个元素
> lpop mylist
"A"
# 从右边推出一个元素
> rpop mylist
"F"
> lrange mylist 0 -1
1) "B"
2) "C"
3) "D"
4) "E"
队列的截取:ltrim
> lrange mylist 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
# 保留队列中索引0到2的元素
> ltrim mylist 0 2
OK
> lrange mylist 0 -1
1) "1"
2) "2"
3) "3"
LTRIM 的一个常见用法是和 LPUSH / RPUSH 一起使用。 例如:
LPUSH mylist someelement
LTRIM mylist 0 99
这一对命令会将一个新的元素 push 进列表里,并保证该列表不会增长到超过100个元素。
队列的阻塞:blpop、brpop、brpoplpush、rpoplpush
blpop 是lpop的阻塞版本。使用lpop时,若列表为空,则直接返回nil。而blpop可以设置超时时间timieout,超时时间内获取不到则为阻塞,超过规定时间列表一直没有数据存入则返回nil;当给定多个列表key值时,会依次找到非空队列,输出队列key值和推出的队列元素。
# mylist1队列为空
> lrange mylist1 0 -1
(empty list or set)
# 推入mylist2元素
> rpush mylist2 a b c
(integer) 3
# 使用blpop依次获取非空队列的头个元素,超时时间为0(即若所有列表为空,立刻返回nil)
> blpop mylist1 mylist2 0
1) "mylist2"
2) "a"
阻塞等待演示:blpop、brpop
客户端1 | 客户端2
# mylist1队列为空
> lrange mylist1 0 -1
(empty list or set)
# blpop阻塞从左则推出数据,超时时间10秒
> blpop mylist1 10
# 此时mylist为空,blpop为阻塞状态
# 此时在客户端2向mylist1推入数据
> lpush mylist1 a b c
(integer) 3
# 客户端1获取数据,阻塞结束
1) "mylist1"
2) "c"
(2.06s) #阻塞时间
rpoplpush/brpoplpush的应用
rpoplpush
命令将一个队列元素推入到另一个队列中。而brpoplpush
就是rpoplpush
的阻塞模式。
> lrange mylist1 0 -1
1) "a"
2) "b"
3) "c"
> lrange mylist2 0 -1
1) "1"
2) "2"
3) "3"
# 将mylist1的最后一个元素推入到mylist2的第一个元素位置
> rpoplpush mylist1 mylist2
"c"
> lrange mylist1 0 -1
1) "a"
2) "b"
> lrange mylist2 0 -1
1) "c"
2) "1"
3) "2"
4) "3"
rpoplpush/brpoplpush的应用举例:
第一种:安全队列
一个简单的队列模式就是:生产者把消息放入一个列表中,等待消息的消费者用 RPOP 命令消费,当消费获取到推出的数据后,还没来的及处理出现了网络或后端崩掉了,那么这个数据就丢失了。可以使用RPOPLPUSH (或者其阻塞版本的 BRPOPLPUSH) 提供了一种方法来避免这个问题:消费者端取到消息的同时把该消息放入一个正在处理中的列表。 当消息被处理了之后,该命令会使用 LREM 命令来移除正在处理中列表中的对应消息。针对长时间存在在处理中列表中的消息,说明该数据已经丢失,将它重新放回到原队列中,等待消费。
第二种:循环队列
当rpoplpush的两个参数队列是同一个队列时,客户端就可以循环访问队列中的数据。
Hash(哈希数据)
hash 就像一个键值对的映射表,理论上可以存储40亿对键值对(前提内存够用),很适合存储对象。
数据存取:hset / hget、hmset / hmget、hgetall
# 单个存取
> hset user:196 name Jack
(integer) 1
> hget user:196 name
"Jack"
# 多键值对存取
> hmset user:196 age 17 birthday 2020-01-02
OK
> hmget user:196 age birthday
1) "17"
2) "2020-01-02"
# 获取所有键值对
> hgetall user:196
1) "name"
2) "Jack"
3) "age"
4) "17"
5) "birthday"
6) "2020-01-02"
获取hash字段数量、所有key或值:hlen、hkeys、hvals
# 获取hash映射表字段数量
> hlen user:196
(integer) 3
# 获取hash映射表所有字段
> hkeys user:196
1) "name"
2) "age"
3) "birthday"
# 获取hash映射表所有字段值
> hvals user:196
1) "Jack"
2) "17"
3) "2020-01-02"
hash表中字段判断、删除:hexists、hdel
# hash表字段判断
> hexists user:196 birthday
(integer) 1
# 字段删除
> hdel user:196 birthday
(integer) 1
> hkeys user:196
1) "name"
2) "age"
Sets(集合)
Sets是字符串类型的数据集合,有数据唯一、无序的属性。
集合的存取、属性、存在判断:sadd、smembers、scard、sismember
> sadd myset 1 2 1 3
(integer) 3
# 获取集合所有元素
> smembers myset
1) "1"
2) "2"
3) "3"
# 获取集合元素个数
> scard myset
(integer) 3
# 判断元素是否存在
> sismember myset 3
(integer) 1
> sismember myset 5
(integer) 0
获取集合中的一个或多个元素:spop、srem、srandmembers
# 集合当前数据
> smembers myset
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "9"
# 删除3、7元素
> srem myset 3 7
(integer) 2
# 随机删除一个元素
> spop myset
"2"
# 随机读3个元素(不从集合中删除)
> srandmember myset 3
1) "4"
2) "6"
3) "1"
> smembers myset
1) "1"
2) "4"
3) "5"
4) "6"
5) "8"
6) "9"
多集合的合集、交集及判断:sdiff、sdiffstore、sinter、sinterstore
> sadd myset1 1 2 3 4
(integer) 4
> sadd myset2 3 4 5 6
(integer) 4
# 查询myset1与myset2的差集
> sdiff myset1 myset2
1) "1"
2) "2"
# 将myset1余myset2的差集存入myset1-2
> sdiffstore myset1-2 myset1 myset2
(integer) 2
127.0.0.1:6379> smembers myset1-2
1) "1"
2) "2"
Sorted Set (有序集合)
有序集合和集合一样也是 string 类型元素的集合,且元素唯一。但可以关联一个double类型的分数,也正是通过这个分数进行排序。
数据的存取:zadd、zrange、zrevrange、zrangebyscore
# zadd集合存储
> zadd users 1995 Tony
(integer) 1
# 获取全部数据包括分数
> zrange users 0 -1 withscores
1) "Tom"
2) "1991"
3) "Jack"
4) "1992"
5) "Tony"
6) "1995"
7) "Bob"
8) "2001"
# 获取1992年前出生的
> zrangebyscore users -inf 1992
1) "Tom"
2) "Jack"
# 获取1992至1995年出生用户, ‘(’表示不包括
> zrangebyscore users (1992 1995
1) "Tony"
-inf表示负无穷;+inf表示正无穷。
集合元素位置判断、删除元素:zrank、zrem、zremrangebyscore
# 获取元素Bob在有序集合中的位置
> zrank users Bob
(integer) 3
# 删除指定元素
> zrem users Tom
(integer) 1
# 删除1992年前的数据
> zremrangebyscore users -inf 1992
(integer) 2
> zrange users 0 -1 withscores
1) "Tony"
2) "1995"
3) "Bob"
4) "2001"
Bitmaps(比特类型)
bitmap可以认为是用一个bit位来映射元素的状态。每一个bit位只有0和1两张状态,非常节省内存。
数据存取:setbit、getbit、bitcount、bitpos
# 将用户10的状态存为1
> setbit user:online 10 1
(integer) 0
# 获取用户10的状态
> getbit user:online 10
(integer) 1
# 获取范围内状态为1的用户数量
> bitcount user:online
(integer) 1
# 获取第一个bit位为1的位置
> bitpos user:online 1
(integer) 10
bitmaps交差判断:bitop
bitop对多个bitmaps数据进行位操作,并保存结果到目标key上。支持 AND 、 OR 、 NOT 、 XOR 四种操作。
# 将user1中和user2中比特位都为1的状态保存到user3中
> BITOP AND user3 user1 user2
(integer) 2
HyperLogLogs
hyperLogLogs是用来做基数统计的,及时是很大的数据量,它所占用的内存都是固定的。
数据存储、统计、合并:pfadd、pfconut、pfmerage
# 存储数据到tag中
> pfadd tag java c++ php java
(integer) 1
# 判断tag中的数据量
> pfcount tag
(integer) 3
# 存储数据到tag1中
> pfadd tag1 python golang java
(integer) 1
# 合并tag和tag1的数据量到tagall中
> pfmerge tagall tag tag1
OK
# 查询结果
> pfcount tagall
(integer) 5