Redis入门1-数据结构

这一章主要描述Redis的基本数据结构以及应用

Redis的数据结构

类型 简介 特性 场景
String(字符串) 二进制安全 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M
Hash(字典) 键值对集合,即编程语言中的Map类型 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去) 1. 存储、读取、修改用户属性 2. 购物车
List(列表) 链表(双向链表) 增删快,提供了操作某一段元素的API 1. 最新消息排行等功能(比如朋友圈的时间线) 2. 消息队列 3. 最近联系人
Set(集合) 哈希表实现,元素不重复 1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作 1. 标签 2. 去重 3. 关注模型 4. 抽奖
Sorted Set(有序集合) 将Set中的元素增加一个权重参数score,元素按score有序排列 数据插入集合时,已经进行天然排序 1. 时间轴 2. 排行榜

字符串应用场景

1
2
3
4
5
6
7
8
9
10
11
12
SET key val										//存入字符串键值对
MSET key value [key val ...] //批量存储字符串键值对
SETNX key value //存入一个不存在的字符串键值对
GET key //获取一个字符串键值
MGET key [...] //批量获取键值对
DEL key [key ...] //删除一个键

//原子加减
INCR key //将key中存储的数字值加1
DECR key //将key中存储的数字值减1
INCRBY key increment //将key所存储的值加上increment
DECR key increment //将key所存储的值加上decrement
  • 在原子加减中,如果 val 不是数字,那么将报错 (error) ERR value is not an integer or out of range
  • SETNX 只会存入一个不存在的值,如果存入成功则返回1,否则返回0

应用1:单值缓存

1
2
3
4
5
6
7
8
//单值缓存
set key value
get key

//对象缓存
set key value(json)
mset k1 v1 k2 v2
mget k1 k2

应用2:分布式锁

由于SETNX(set if not exist)无法设置key的有效期,导致锁可能成为死锁,可以使用set完成锁操作,并且是原子操作

1
set key value [EX seconds] [PX milliseconds] [NX/XX]
  • EX seoncds: 设置失效时长,单位秒
  • PX milliseconds: 设置失效时长,单位毫秒
  • NX: key不存在时设置value,成功返回OK,失败返回(nil)
  • XX: key存在时设置value,成功返回OK,失败返回(nil)

应用3:计数器

比如记录文章阅读次数(如果使用数据库,则需要考虑并发锁),incrby命令可以实现原子性的递增

1
2
INCR article:readcount:{文章id}
GET article:readcount:{文章id}

Hash应用场景

1
2
3
4
5
6
7
8
HSET key field value				//存储一个哈希表的键值
HSETNX key field value //存储一个不存在的哈希表Key
HMSET key field value [field value ...] //在一个哈希表key中存储多个键值对
HGET key field //获取hash表中key对应的field键值对
HMGT key field [field ...] //批量获取哈希表key中多个field的值
HDEL key field [field ...] //删除哈希表中key的多个field的值
HLEN key //返回哈希表中key的field的数量
HINCRBY key field increment //为哈希表key中filed的值加上增量

应用1:购物车

第一步,新增商品到购物车中

1
hset cart:1001 10088 1
  • cart代表的购物车
  • :1001 这里代表的是用户id
  • 10088 代表的是商品id
  • 1 代表数量

第二步,增加商品数量1

1
hincrby cert:1001 10088 1

第三步,获取购物车中商品总量

1
2
3
4
5
#获取数量
hlen cert:1001

#获取所有键值对
hgetall cert:1001

第四步,删除购物车内容

1
2
#删除购物车
hdel cert:1001

优点:

  1. 同类数据归类整合存储方便数据管理
  2. 相比string操作消耗内存与cpu更小
  3. 相比string存储更节省空间

缺点:

  1. 过期功能不能使用在field上,只能用在key上
  2. hash的会分配槽位,Redis集群架构下集群中会导致数据过于集中,没办法做分片

List应用场景

1
2
3
4
5
6
7
lpush key value [...value] 				#将一个或多个值value插入到key列表的表头(最左边)
rpush key value [...value] #将一个或多个值value插入到key列表的表尾(最右边)
lpop key #移除并返回key列表的头元素
rpop key #移除并返回key列表的尾元素
lrange key start stop #返回列表key中制定区间的元素,区间异偏移量start和stop指定
blpop key [key ...] timeout #从key表头弹出一个元素,若没有元素则阻塞等待timeout秒,如果timeout = 0,则一直阻塞
brpop key [key ...] timeout #从key表尾弹出一个元素,若没有元素则阻塞等待timeout秒,如果timeout = 0,则一直阻塞

应用1:最近联系人

1
2
3
4
5
6
#1. 首先存储新的联系人
lpush contact:我的id 小明的ID
lpush contact:我的id 小强的ID
lpush contact:我的id 小白的ID
#2. 只保留2位
ltrim contact:我的id 0 2 #返回小强的ID 、小白的ID

Set 应用场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SADD key member [member ...]	//往集合key中存入元素,元素存在则忽略,不存在则新建
SREM key member [member ...] //从集合中删除元素
SMEMBERS key //获取即可key中所有元素
SCARD key //获取集合key的元素个数
SISMEMBER key member //判断key是否存在于集合中
SRANDMEMBER key [count] //从集合key中选出count个元素,元素不从key中删除
SPOP key [count] //从结合key中选出count个元素,元素从key中删除

SINTER key [key ...] //交集运算
SINTERSTORE destionation key [key ...] //交集运算的结果存入新集合 destionation中
SUNION key[key ...] //并集运算
SUNIONSTORE destionation key [key ...] //并集运算的结果存入新集合 destionation中
SDIFF key [key ...] //差集运算
SDIFFSOTRE destionation key [key ...] //差集运算的结果存入新集合 destionation中

应用1:去重

由于Set是一种无序,不重复的数据结构,所以用户的操作可以存储在Set中,避免重复操作

1
2
3
4
5
#重复添加 k/v
SADD myset "hello"
SADD myset "hello"
SADD myset "world"
SMEMBERS myset #只得到 “hello” "world" 两个值

应用2:标签

记录博客点赞、收藏、标签数。首先是知道自己被谁点赞、收藏,另外是需要知道自己点赞、收藏了哪些

1
2
3
4
5
6
7
8
9
10
11
12
#1. 点赞(消息被谁点赞)
SADD like:{消息ID} {用户ID}
#2. 取消点赞(删除消息的点赞)
SREM like:{消息ID} {用户ID}
#3. 检查用户是否点赞过
SISMEMBER like:{消息ID} {用户ID}
#4. 获取点赞的用户列表
SMEMBERS like:{消息ID}
#5. 获取点赞用户数
SCARD like:{消息ID}
#6. 消息贴标签
SADD tag:{消息ID} {标签ID}

应用3:关注模型

1
2
3
4
5
6
7
8
9
10
11
12
13
#1. 你关注的人
SADD following:我的ID {张三、李四、王五}
#2. 小明关注的人
SADD following:小明ID {张三、王五、刘六}
#3. 小强关注的人
SADD following:小强ID {七七、小八}
#4. 我跟小明的共同关注
SINTER following:我的ID following:小明ID #张三、王五
#5. 我关注的人也在关注小明
SISMEMBER following:我的ID 小白ID #我是否关注了小白
SISMEMBER following:小白ID 小明ID #小白是否关注了小明
#6. 我可能认识的人(我关注了小明、小明关注的就是我可能认识的人)
SDIFF following:我的ID following:小明

应用4:抽奖

1
2
3
4
5
6
#1. 将用户加入集合
SADD key {userID}
#2. 查看参与抽奖的所有用户
SMEMBERS key
#3. 抽取count名中奖者
SRANDMEMBER key [couunt] / SPOP key [count]

SortedSet 应用场景

1
2
3
4
5
6
7
8
ZADD key score1 member1 [score2 member2 ...]	#往集合key中存入元素,或更新成员分数
ZCARD key #获取集合key的元素个数
ZCOUNT key min max #计算在有序集合中指定区间分数的成员数
ZINCRBY key increment member #有序集合中对指定成员的分数加上增量
ZINTERSTORE destination numkeys key [key ...] # 计算给定的多个有序集的交集并将结果集存储在新的有序集合 destination 中
ZLEXCOUNT key min max #在有序集合中计算指定字典区间内成员数量
ZREM key member [member ...] #移除有序集合中的一个或多个成员
ZSCORE key member #返回有序集中,成员的分数值

应用1:时间轴

1
2
# 每隔5min记录一次温度
ZADD temperature:我的ID 123124 30.5 234235 33.5

应用2:排行榜

1
2
3
4
5
6
7
8
9
# 添加用户得分
ZADD leaderboard 90 "Alice"
ZADD leaderboard 80 "Bob"
ZADD leaderboard 70 "Charlie"
ZADD leaderboard 60 "Dave"
ZADD leaderboard 50 "Eva"

# 获取排行榜前三名
ZREVRANGE leaderboard 0 2 WITHSCORES

参考链接

  1. https://www.runoob.com/redis/redis-data-types.html
  2. http://doc.redisfans.com
  3. https://segmentfault.com/a/1190000038173551