Redis五种核心数据结构、应用场景及实现
前言
一、Redis常用的场景
-
缓存
缓存现在几乎是所有中大型网站都在用的必杀技,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力。Redis提供了键过期功能,也提供了灵活的键淘汰策略。所以,现在Redis用在缓存的场合非常多。 -
排行榜
很多网站都有排行榜应用的,如京东的月度销量榜单、商品按时间的上新排行榜等。Redis提供的有序集合数据类构能实现各种复杂的排行榜应用。 -
计数器
什么是计数器,如电商网站商品的浏览量、视频网站视频的播放数等。为了保证数据实时效,每次浏览都得给+1,并发量高时,如果每次都请求数据库操作无疑是种挑战和压力。Redis提供的incr命令来实现计数器功能,内存操作,性能非常好,非常适用于这些计数场景。 -
分布式会话
集群模式下,在应用不多的情况下一般使用容器自带的session复制功能就能满足,当应用增多相对复杂的系统中,一般都会搭建以Redis等内存数据库为中心的session服务,session不再由容器管理,而是由session服务及内存数据库管理。 -
分布式锁
在很多互联网公司中都使用了分布式技术,分布式技术带来的技术挑战是对同一个资源的并发访问,如全局ID、减库存、秒杀等场景,并发量不大的场景可以使用数据库的悲观锁、乐观锁来实现,但在并发量高的场合中,利用数据库锁来控制资源的并发访问是不太理想的,大大影响了数据库的性能。可以利用Redis的setnx功能来编写分布式的锁,如果设置返回1说明获取锁成功,否则获取锁失败,实际应用中要考虑的细节要更多。 -
社交网络
点赞、踩、关注/被关注、共同好友等是社交网站的基本功能,社交网站的访问量通常来说比较大,而且传统的关系数据库类型不适合存储这种类型的数据,Redis提供的哈希、集合等数据结构能很方便的的实现这些功能。 -
最新列表
Redis列表结构,LPUSH可以在列表头部插入一个内容ID作为关键字,LTRIM可用来限制列表的数量,这样列表永远为N个ID,无需查询最新的列表,直接根据ID去到对应的内容页即可。 -
消息系统
消息队列是大型网站必用中间件,如ActiveMQ、RabbitMQ、Kafka等流行的消息队列中间件,主要用于业务解耦、流量削峰及异步处理实时性低的业务。Redis提供了发布/订阅及阻塞队列功能,能实现一个简单的消息队列系统。另外,这个不能和专业的消息中间件相比。
二、String结构
2.1常用操作命令
常用操作命令 | 说明 |
---|---|
SET key value | 存入字符串键值对 |
MSET key value[key value … ] | 批量存储字符串键值对 |
SETNX key value | 存入一个不存在的字符串键值对 |
GET key | 获取一个字符串键值 |
MGET key [key … ] | 批量获取字符串键值 |
DEL key [key … ] | 删除一个键 |
EXPIRE key seconds | 设置一个键的过期时间(秒) |
原子加减
常用操作命令 | 说明 |
---|---|
INCR key | 将key中储存的数字值加1 |
DECR key | 将key中储存的数字值减1 |
INCRBY key increment | 将key所储存的值加上increment |
DECRBY key decrement | 将key所储存的值减去decrement |
2.3String应用场景
- 单值缓存
1) SET key value
2) GET key
- 对象缓存
1) SET user:1 value(json格式数据)
2) MSET user:1:name zs user:1:balance 1000
MGET user:1:name user:1 :balance
- 分布式锁
命令 | 说明 |
---|---|
SETNX product:10001 true | 返回1代表获取锁成功 |
SETNX product:10001 false | 返回0代表获取锁失败 |
DEL product:10001 | 执行完业务释放锁 |
SET product:10001 true ex 10 nx | 防止程序意外终止导致死锁 |
- 计数器
1)INCR article:readcount:{文章id}
2)GET article:readcount:{文章id}
-
Web集群session共享
spring session + redis实现session共享 -
分布式系统全局序列号
INCRBY orderld 1000 //redis批量生产序列号提升性能
三、Hash结构
Hash的结构相当于value里面又放了一个key-value的键值对。
优点:
1)同类数据归类整合储存,方便数据管理
2)相比string操作消耗内存与cpu更小
3)相比string储存更节省空间
缺点:
1)过期功能不能使用在field上,只能用在key上
2) Redis集群架构下不适合大规模使用
3.1常用操作命令
常用操作命令 | 说明 |
---|---|
HSET key field value | 存储一一个哈希表key的键值 |
HSETNX key field value | 存储一个不存在的哈希表key的键值 |
HMSET key field value [field value …] | 在一一个哈希表key中存储多个键值对 |
HGET key field | 获取哈希表key对应的field键值 |
HMGET key field [field …] | 批量获取哈希表key中多个field键值 |
HDEL key field [field …] | 删除哈希表key中的field键值 |
HLEN key | 返回哈希表key中field的数量 |
HGETALL key | 返回哈希表key中所有的键值 |
HINCRBY key field increment | 为哈希表key中field键的值加上增量increment |
3.2Hash应用场景
- 对象缓存
HMSET user (userld):name zs(userld):balance 1000
HMSET user 1:name zhuge 1:balance 1888
HMGET user 1:name 1:balance
- 电商购物车
购物车操作
1)添加商品>hset cart:1001 10088 1
2)增加数量→hincrby cart:1001 10088 1
3)商品总数→hlen cart:1001
4)删除商品>hdel cart:1001 10088
5)获取购物车所有商品>hgetall cart:1001
四、List结构
4.1常用操作命令
常见操作命令 | 说明 |
---|---|
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,一直阻塞等待 |
4.2List应用场景
- 实现常用数据结构
Stack(栈) = LPUSH + LPOP -> FILO
Queue(队列) = LPUSH + RPOP
Blocking MQ(阻塞队列) = LPUSH + BRPOP
- 微博和微信公众号消息流
小王关注了公众号1和公众号2
1)公众号1发了文章,消息ID为100181
LPUSH msg:小王-ID} 100181)
2)公众号2发了文章,消息ID为100182
LPUSH msg:小王-1D} 100182
3)查看最新微博消息
LRANGE msg:{小王-ID} 0 4
五、Set结构
SINTER set1 set2 set3 ->{c}
SUNION set1 set2 set3 -> {a,b,c,d,e}
SDIFF set1 set2 set3 -> {a}
5.1常用操作命令
常见操作命令 | 说明 |
---|---|
SADD key member [member …] | 往集合key中存入元素,元素存在则忽略,若key不存在则新建 |
SREM key member [member …] | 从集合key中删除元素 |
SMEMBERS key | 获取集合key中所有元素 |
SCARD key | 获取集合key的元素个数 |
SISMEMBER key member | 判断member元素是否存在于集合key中 |
SRANDMEMBER key [count] | 从集合key中选出count个元素,元素不从key中删除 |
SPOP key [count] | 从集合key中选出count个元素,元素从key中删除 |
5.2Set应用场景
- 微信抽奖小程序
1)点击参与抽奖加入集合
SADD key {userlD}
2)查看参与抽奖所有用户
SMEMBERS key
3)抽取count名中奖者
SRANDMEMBER key [count] / SPOP key [count]
- 微信或微博的点赞,评论,收藏,标签
1)点赞
SADD like:{消息ID} {用户ID}
2)取消点赞
SREM like:{消息ID} {用户ID}
3)检查用户是否点过赞
SISMEMBER like:{消息ID} {用户ID}
4)获取点赞的用户列表
SMEMBERS like:{消息ID}
5)获取点赞用户数
SCARD like:{消息ID}
- 集合运算操作实现微信微信关注模型
运算操作命令 | 说明 |
---|---|
SINTER key [key …] | 交集运算 |
SINTERSTORE destination key [key …] | 将交集结果存入新集合destination中 |
SUNION key [key …] | 并集运算 |
SUNIONSTORE destination key [key …] | 将并集结果存入新集合destination中 |
SDIFF key [key …] | 差集运算 |
SDIFFSTORE destination key [key …] | 将差集结果存入新集合destination中 |
比如小饶关注的人、小饶的粉丝、小汤和小饶共同关注的人、小饶可能认识的人
六、ZSet结构
6.1常用操作命令
常见操作命令 | 说明 |
---|---|
ZADD key score member [score member…] | 往有序集合key中加入带分值元素 |
ZREM key member [member …] | 从有序集合key中删除元素 |
ZSCORE key member | 返回有序集合key中元素member的分值 |
ZINCRBY key increment member | 为有序集合key中元素member的分值加上increment |
ZCARD key | 返回有序集合key中元素个数 |
ZRANGE key start stop [WITHSCORES] | 正序获取有序集合key从start下标到stop下标的元素 |
ZREVRANGE key start stop [WITHSCORES] | 倒序获取有序集合key从start 下标到stop下标的元素 |
ZUNIONSTORE destkey numkeys key [key …] | 并集计算 |
ZINTERSTORE destkey numkeys key [key …] | 交集计算 |
6.2ZSet应用场景
ZSet集合操作实现排行榜
1)点击新闻
ZINCRBY hotNews:20190819 1 新闻1
2)展示当日排行前十
ZREVRANGE hotNews:20190819 0 9 WITHSCORES
3)七日搜索榜单计算
ZUNIONSTORE hotNews:20190813-20190819 7
hotNews:20190813 hotNews:20190814.. hotNews:20210819
4)展示七日排行前十
ZREVRANGE hotNews:20190813-20190819 0 9 WITHSCORES