本篇介绍Redis常用的五种数据类型字符串string、哈希hash、列表list、集合set以及有序集合zset。
1. 字符串string
1.1 基本操作
1.1.1 存入一个字符串
set mykey somevalue
1.1.2 获取一个字符串
get mykey
1.1.3 批量存储多个字符串
mset a 10 b 20 c 30
1.1.4 批量获取多个字符串
mget a b c
1.1.5 查询key是否存在
返回1为存在,0为不存在
exists mykey
1.1.6 删除key
返回1是被删除,0是没被删除
del mykey
1.1.7 返回key对应的值的存储类型
type mykey
1.1.8 设置和查询key的超时时间
创建时设置超时时间
set key 100 ex 10
单独设置超时时间
expire key 5
查询key的超时时间
ttl key
1.1.9 原子操作
将key中存储的值加1
incr key
将key中存储的值减1
decr key
将key所存储的值加上指定值
incrby key 10
将key所存储的值减去指定值
decrby key 10
1.2 应用场景
1.2.1 单值缓存
保存商品库存,key是商品id,value是库存数量
set 101 10
1.2.2 对象缓存
适用于数据不断变化的应用场景
mset user:1:name zyz user:1:age 18
1.2.3 分布式锁
setnx product:101 true //返回1代表获取锁成功
setnx product:101 true //返回0代表获取锁失败
del product:101 //执行完业务逻辑释放锁
set product:101 true ex 10 nx //防止程序意外终止导致死锁
1.2.4 计数器
文章访问量,每当用户访问,阅读数加1
incr article:readcount:101
1.2.5 分布式系统全局序列号
从Redis拿到1000个ID,然后放入本地缓存,慢慢处理
incrby orderId 1000
2. 哈希hash
2.1 基本操作
2.1.1 将哈希表 key 中的域 field 的值设为 value
redis> HSET website redis "redis.com" # 设置一个新域
(integer) 1
2.1.2 返回哈希表 key 中给定域 field 的值
redis> HSET site redis redis.com
(integer) 1
redis> HGET site redis
"redis.com"
2.1.3 返回哈希表 key 中,所有的域和值
redis> HSET people jack "Jack Sparrow"
(integer) 1
redis> HSET people gump "Forrest Gump"
(integer) 1
redis> HGETALL people
1) "jack" # 域
2) "Jack Sparrow" # 值
3) "gump"
4) "Forrest Gump"
2.1.4 同时将多个 field-value (域-值)对设置到哈希表 key 中
redis> HMSET website google www.google.com yahoo www.yahoo.com
OK
redis> HGET website google
"www.google.com"
redis> HGET website yahoo
"www.yahoo.com"
2.1.5 返回哈希表 key 中,一个或多个给定域的值
redis> HMSET pet dog "doudou" cat "nounou" # 一次设置多个域
OK
redis> HMGET pet dog cat fake_pet # 返回值的顺序和传入参数的顺序一样
1) "doudou"
2) "nounou"
3) (nil) # 不存在的域返回nil值
2.1.6 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在
redis> HSETNX nosql key-value-store redis
(integer) 1
redis> HSETNX nosql key-value-store redis # 操作无效,域 key-value-store 已存在
(integer) 0
2.1.7 返回哈希表 key 中域的数量
redis> HSET db redis redis.com
(integer) 1
redis> HSET db mysql mysql.com
(integer) 1
redis> HLEN db
(integer) 2
redis> HSET db mongodb mongodb.org
(integer) 1
redis> HLEN db
(integer) 3
2.1.8 删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略
# 测试数据
redis> HGETALL abbr
1) "a"
2) "apple"
3) "b"
4) "banana"
5) "c"
6) "cat"
7) "d"
8) "dog"
# 删除单个域
redis> HDEL abbr a
(integer) 1
# 删除不存在的域
redis> HDEL abbr not-exists-field
(integer) 0
# 删除多个域
redis> HDEL abbr b c
(integer) 2
redis> HGETALL abbr
1) "d"
2) "dog"
2.1.9 为哈希表 key 中的域 field 的值加上增量 increment
# increment 为正数
redis> HEXISTS counter page_view # 对空域进行设置
(integer) 0
redis> HINCRBY counter page_view 200
(integer) 200
redis> HGET counter page_view
"200"
# increment 为负数
redis> HGET counter page_view
"200"
redis> HINCRBY counter page_view -50
(integer) 150
redis> HGET counter page_view
"150"
# 尝试对字符串值的域执行HINCRBY命令
redis> HSET myhash string hello,world # 设定一个字符串值
(integer) 1
redis> HGET myhash string
"hello,world"
redis> HINCRBY myhash string 1 # 命令执行失败,错误。
(error) ERR hash value is not an integer
redis> HGET myhash string # 原值不变
"hello,world"
2.2 应用场景
2.2.1 对象缓存
HMSET user 101:name zyz 101:age 18
HMGET user 101:name 101:age
2.2.2 电商购物车
- 以用户id为key
- 商品id为field
- 商品数量为value
购物车操作
hset cart:101 1888 1 //添加商品
hincrby cart:101 1888 1 //增加数量
hlen cart:101 //商品总数
hdel cart:101 1888 //删除商品
hgetall cart:101 //获取购物车所有商品
3. 列表list
3.1 基本操作
3.1 将一个或多个值 value 插入到列表 key 的表头
# 加入单个元素
redis> LPUSH languages python
(integer) 1
# 加入重复元素
redis> LPUSH languages python
(integer) 2
redis> LRANGE languages 0 -1 # 列表允许重复元素
1) "python"
2) "python"
# 加入多个元素
redis> LPUSH mylist a b c
(integer) 3
redis> LRANGE mylist 0 -1
1) "c"
2) "b"
3) "a"
3.1.2 将一个或多个值 value 插入到列表 key 的表尾(最右边)
# 添加单个元素
redis> RPUSH languages c
(integer) 1
# 添加重复元素
redis> RPUSH languages c
(integer) 2
redis> LRANGE languages 0 -1 # 列表允许重复元素
1) "c"
2) "c"
# 添加多个元素
redis> RPUSH mylist a b c
(integer) 3
redis> LRANGE mylist 0 -1
1) "a"
2) "b"
3) "c"
3.1.3 移除并返回列表 key 的头元素
redis> LLEN course
(integer) 0
redis> RPUSH course algorithm001
(integer) 1
redis> RPUSH course c++101
(integer) 2
redis> LPOP course # 移除头元素
"algorithm001"
3.1.4 移除并返回列表 key 的尾元素
redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> RPOP mylist # 返回被弹出的元素
"three"
redis> LRANGE mylist 0 -1 # 列表剩下的元素
1) "one"
2) "two"
3.1.5 从key列表表头弹出一个元素,若列表中没有元素,阻塞等待 timeout秒,如果timeout=0,一直阻塞等待
blpop key [key...] timeout
3.1.6 从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待 timeout秒,如果timeout=0,一直阻塞等待
brpop key [key...] timeout
3.2 应用场景
3.2.1 常用数据结构
- Stack(栈) = LRUSH + LPOP
- Queue(队列) = LPUSH + RPOP
- Blocking MQ(阻塞队列) = LPUSH + BRPOP
3.2.2 微博信息和微信公众号信息
小明关注了遇见北京、阿里技术等大V
- 遇见北京发微博,消息ID为1001
LPUSH msg:101 1001
- 阿里技术发微博,消息ID为1002
LPUSH msg:101 1002
- 查看最新微博消息
LRANGE msg:101 0 4
4. 集合set
4.1 常用操作
4.1.1 往集合key中存入元素,元素存在则忽略,若key不存在则新建
# 添加单个元素
redis> SADD bbs "discuz.net"
(integer) 1
# 添加重复元素
redis> SADD bbs "discuz.net"
(integer) 0
# 添加多个元素
redis> SADD bbs "tianya.cn" "groups.google.com"
(integer) 2
redis> SMEMBERS bbs
1) "discuz.net"
2) "groups.google.com"
3) "tianya.cn"
4.1.2 从集合key中删除元素
# 测试数据
redis> SMEMBERS languages
1) "c"
2) "lisp"
3) "python"
4) "ruby"
# 移除单个元素
redis> SREM languages ruby
(integer) 1
# 移除不存在元素
redis> SREM languages non-exists-language
(integer) 0
# 移除多个元素
redis> SREM languages lisp python c
(integer) 3
redis> SMEMBERS languages
(empty list or set)
4.1.3 获取集合key中所有元素
# key 不存在或集合为空
redis> EXISTS not_exists_key
(integer) 0
redis> SMEMBERS not_exists_key
(empty list or set)
# 非空集合
redis> SADD language Ruby Python Clojure
(integer) 3
redis> SMEMBERS language
1) "Python"
2) "Ruby"
3) "Clojure"
4.1.4 获取集合key的元素个数
redis> SADD tool pc printer phone
(integer) 3
redis> SCARD tool # 非空集合
(integer) 3
redis> DEL tool
(integer) 1
redis> SCARD tool # 空集合
(integer) 0
4.1.5 判断member元素是否存在于集合key中
redis> SMEMBERS joe's_movies
1) "hi, lady"
2) "Fast Five"
3) "2012"
redis> SISMEMBER joe's_movies "bet man"
(integer) 0
redis> SISMEMBER joe's_movies "Fast Five"
(integer) 1
4.1.6 从集合key中选出count个元素,元素不从key中删除
# 添加元素
redis> SADD fruit apple banana cherry
(integer) 3
# 只给定 key 参数,返回一个随机元素
redis> SRANDMEMBER fruit
"cherry"
redis> SRANDMEMBER fruit
"apple"
# 给定 3 为 count 参数,返回 3 个随机元素
# 每个随机元素都不相同
redis> SRANDMEMBER fruit 3
1) "apple"
2) "banana"
3) "cherry"
# 给定 -3 为 count 参数,返回 3 个随机元素
# 元素可能会重复出现多次
redis> SRANDMEMBER fruit -3
1) "banana"
2) "cherry"
3) "apple"
redis> SRANDMEMBER fruit -3
1) "apple"
2) "apple"
3) "cherry"
# 如果 count 是整数,且大于等于集合基数,那么返回整个集合
redis> SRANDMEMBER fruit 10
1) "apple"
2) "banana"
3) "cherry"
# 如果 count 是负数,且 count 的绝对值大于集合的基数
# 那么返回的数组的长度为 count 的绝对值
redis> SRANDMEMBER fruit -10
1) "banana"
2) "apple"
3) "banana"
4) "cherry"
5) "apple"
6) "apple"
7) "cherry"
8) "apple"
9) "apple"
10) "banana"
# SRANDMEMBER 并不会修改集合内容
redis> SMEMBERS fruit
1) "apple"
2) "cherry"
3) "banana"
# 集合为空时返回 nil 或者空数组
redis> SRANDMEMBER not-exists
(nil)
redis> SRANDMEMBER not-eixsts 10
(empty list or set)
4.1.7 从集合key中选出count个元素,元素从key中删除
redis> SMEMBERS db
1) "MySQL"
2) "MongoDB"
3) "Redis"
redis> SPOP db
"Redis"
redis> SMEMBERS db
1) "MySQL"
2) "MongoDB"
redis> SPOP db
"MySQL"
redis> SMEMBERS db
1) "MongoDB"
4.2 运算操作
4.2.1 交集运算
redis> SMEMBERS group_1
1) "LI LEI"
2) "TOM"
3) "JACK"
redis> SMEMBERS group_2
1) "HAN MEIMEI"
2) "JACK"
redis> SINTER group_1 group_2
1) "JACK"
4.2.2 将交集结果存入新集合destination中
redis> SMEMBERS songs
1) "good bye joe"
2) "hello,peter"
redis> SMEMBERS my_songs
1) "good bye joe"
2) "falling"
redis> SINTERSTORE song_interset songs my_songs
(integer) 1
redis> SMEMBERS song_interset
1) "good bye joe"
4.2.3 并集运算
redis> SMEMBERS songs
1) "Billie Jean"
redis> SMEMBERS my_songs
1) "Believe Me"
redis> SUNION songs my_songs
1) "Billie Jean"
2) "Believe Me"
4.2.4 将并集结果存入新集合destination中
redis> SMEMBERS NoSQL
1) "MongoDB"
2) "Redis"
redis> SMEMBERS SQL
1) "sqlite"
2) "MySQL"
redis> SUNIONSTORE db NoSQL SQL
(integer) 4
redis> SMEMBERS db
1) "MySQL"
2) "sqlite"
3) "MongoDB"
4) "Redis"
4.2.5 差集运算
redis> SMEMBERS peter's_movies
1) "bet man"
2) "start war"
3) "2012"
redis> SMEMBERS joe's_movies
1) "hi, lady"
2) "Fast Five"
3) "2012"
redis> SDIFF peter's_movies joe's_movies
1) "bet man"
2) "start war"
4.2.6 将差集结果存入新集合destination中
redis> SMEMBERS joe's_movies
1) "hi, lady"
2) "Fast Five"
3) "2012"
redis> SMEMBERS peter's_movies
1) "bet man"
2) "start war"
3) "2012"
redis> SDIFFSTORE joe_diff_peter joe's_movies peter's_movies
(integer) 2
redis> SMEMBERS joe_diff_peter
1) "hi, lady"
2) "Fast Five"
4.3 应用场景
4.3.1 抽奖小程序
SADD key 101 //点击参与抽奖加入集合
SMEMBERS key //查看参与抽奖所有用户
SRANDMEMBER key [count] / SPOP key [count] //抽取count名中奖者
4.3.2 微博点赞、收藏、标签
SADD like:101 1001 //点赞
SREM like:101 1001 //取消点赞
SISMEMBER like:101 1001 //检查用户是否点过赞
SMEMBERS like:101 //获取点赞的用户列表
SCARD like:101 //获取点赞用户数
4.3.3 集合操作实现微博微信关注模型
- 诸葛亮关注的人: zhugeliangSet -> {guojia, xushu}
- 杨过关注的人: yangguoSet -> {zhugeliang, baiqi, guojia, xushu}
- 郭嘉关注的人: guojiaSet -> {zhugeliang, yangguo, baiqi, xushu, xunyu)
- 诸葛亮和杨过共同关注: SINTER zhugeliangSet yangguoSet--> {guojia, xushu}
- 诸葛亮关注的人也关注杨过:SISMEMBER guojiaSet yangguo
SISMEMBER xushuSet yangguo - 诸葛亮可能认识的人:SDIFF yangguoSet zhugeSet->(zhugeliang, baiqi}
4.3.4 集合操作实现电商商品筛选
SADD brand:huawei P40
SADD brand:xiaomi mi-10
SADD brand:iPhone iphone12
SADD os:android P40 mi-10
SADD cpu:brand:intel P40 mi-10
SADD ram:8G P40 mi-10 iphone12
SINTER os:android cpu:brand:intel ram:8G -> {P40,mi-10}
5. 有序集合zset
5.1 常用操作
5.1.1 往有序集合key中加入带分值元素
# 添加单个元素
redis> ZADD page_rank 10 google.com
(integer) 1
# 添加多个元素
redis> ZADD page_rank 9 baidu.com 8 bing.com
(integer) 2
redis> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 添加已存在元素,且 score 值不变
redis> ZADD page_rank 10 google.com
(integer) 0
redis> ZRANGE page_rank 0 -1 WITHSCORES # 没有改变
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 添加已存在元素,但是改变 score 值
redis> ZADD page_rank 6 bing.com
(integer) 0
redis> ZRANGE page_rank 0 -1 WITHSCORES # bing.com 元素的 score 值被改变
1) "bing.com"
2) "6"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
5.1.2 从有序集合key中删除元素
# 测试数据
redis> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 移除单个元素
redis> ZREM page_rank google.com
(integer) 1
redis> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
# 移除多个元素
redis> ZREM page_rank baidu.com bing.com
(integer) 2
redis> ZRANGE page_rank 0 -1 WITHSCORES
(empty list or set)
# 移除不存在元素
redis> ZREM page_rank non-exists-element
(integer) 0
5.1.3 返回有序集合key中元素member的分值
redis> ZRANGE salary 0 -1 WITHSCORES # 测试数据
1) "tom"
2) "2000"
3) "peter"
4) "3500"
5) "jack"
6) "5000"
redis> ZSCORE salary peter # 注意返回值是字符串
"3500"
5.1.4 为有序集合key中元素member的分值加上increment
redis> ZSCORE salary tom
"2000"
redis> ZINCRBY salary 2000 tom # tom 加薪啦!
"4000"
5.1.5 返回有序集合key中元素个数
redis > ZADD salary 2000 tom # 添加一个成员
(integer) 1
redis > ZCARD salary
(integer) 1
redis > ZADD salary 5000 jack # 再添加一个成员
(integer) 1
redis > ZCARD salary
(integer) 2
redis > EXISTS non_exists_key # 对不存在的 key 进行 ZCARD 操作
(integer) 0
redis > ZCARD non_exists_key
(integer) 0
5.1.6 正序获取有序集合key从start下标到stop下标的元素
redis > ZRANGE salary 0 -1 WITHSCORES # 显示整个有序集成员
1) "jack"
2) "3500"
3) "tom"
4) "5000"
5) "boss"
6) "10086"
redis > ZRANGE salary 1 2 WITHSCORES # 显示有序集下标区间 1 至 2 的成员
1) "tom"
2) "5000"
3) "boss"
4) "10086"
redis > ZRANGE salary 0 200000 WITHSCORES # 测试 end 下标超出最大下标时的情况
1) "jack"
2) "3500"
3) "tom"
4) "5000"
5) "boss"
6) "10086"
redis > ZRANGE salary 200000 3000000 WITHSCORES # 测试当给定区间不存在于有序集时的情况
(empty list or set)
5.1.7 倒序获取有序集合key从start下标到stop下标的元素
redis> ZRANGE salary 0 -1 WITHSCORES # 递增排列
1) "peter"
2) "3500"
3) "tom"
4) "4000"
5) "jack"
6) "5000"
redis> ZREVRANGE salary 0 -1 WITHSCORES # 递减排列
1) "jack"
2) "5000"
3) "tom"
4) "4000"
5) "peter"
6) "3500"
5.2 集合操作
5.2.1 并集计算
redis> ZRANGE programmer 0 -1 WITHSCORES
1) "peter"
2) "2000"
3) "jack"
4) "3500"
5) "tom"
6) "5000"
redis> ZRANGE manager 0 -1 WITHSCORES
1) "herry"
2) "2000"
3) "mary"
4) "3500"
5) "bob"
6) "4000"
redis> ZUNIONSTORE salary 2 programmer manager WEIGHTS 1 3 # 公司决定加薪。。。除了程序员。。。
(integer) 6
redis> ZRANGE salary 0 -1 WITHSCORES
1) "peter"
2) "2000"
3) "jack"
4) "3500"
5) "tom"
6) "5000"
7) "herry"
8) "6000"
9) "mary"
10) "10500"
11) "bob"
12) "12000"
5.2.2 交集计算
redis > ZADD mid_test 70 "Li Lei"
(integer) 1
redis > ZADD mid_test 70 "Han Meimei"
(integer) 1
redis > ZADD mid_test 99.5 "Tom"
(integer) 1
redis > ZADD fin_test 88 "Li Lei"
(integer) 1
redis > ZADD fin_test 75 "Han Meimei"
(integer) 1
redis > ZADD fin_test 99.5 "Tom"
(integer) 1
redis > ZINTERSTORE sum_point 2 mid_test fin_test
(integer) 3
redis > ZRANGE sum_point 0 -1 WITHSCORES # 显示有序集内所有成员及其 score 值
1) "Han Meimei"
2) "145"
3) "Li Lei"
4) "158"
5) "Tom"
6) "199"
5.3 应用场景
5.3.1 排行榜
ZINCRBY hotNews:20190819 1 守护香港 //点击新闻
ZREVRANGE hotNews:20190819 0 9 WITHSCORES //展示当日排行前十
ZUNIONSTORE hotNews:20190813-20190819 7
hotNews:20190813 hotNews:20190814... hotNews:20190819 //七日搜索榜单计算
ZREVRANGE hotNews:20190813-20190819 0 9 WITHSCORE //展示七日排行前十
参考资料
- Redis官网 -> https://redis.io/commands
- Redis中文指令 -> http://doc.redisfans.com/