说起Redis,我百分之一百肯定,大家脑海里第一反应肯定是–缓存,Redis最常见的用法就是缓存了。
在高并发的服务中,MySQL通常是服务性能的瓶颈,这个瓶颈的常规解法是给MySQL添加个Redis缓存,减缓MySQL的数据读压力。
Redis不仅仅可以作为缓存使用,它还有更多的超强用途。这些用途,在工作或者我们的面试中都有可能遇到,想升职加薪,赢得面试官的青睐,学好它准没错!
本文主要讨论Redis几种数据类型的应用场景
String使用场景
常规计数的场景很多,比如下面的这几种场景
- 计数器,例如网页访问次数
- 数据缓存
- 分布式锁
以上是String数据类型的使用场景,接下来,我们来看看每种使用场景如何使用
计数器(网页访问统计)
我们先以计数器(网页访问统计)使用场景为例,看看怎么使用Redis实现网页的访问统计。在这个场景里,可以使用userid:pageviews
作为key,假设userid为123,那么key为123:pageviews
- 初始化计数器
在我们服务启动的时候,可以使用redis的set
命令初始化计数器
# 初始化计数器
SET userid:pageviews 0
当然,我们也可以直接使用INCR
或者DECR
命令,如果一开始就不存在pageviews
的话,redis会将pageviews
设置为0,然后再执行操作
- 计数器增加
当网页进行了一次访问后,我们需要对pageviews进行+1操作,这时候,需要执行INCR
命令
INCR userid:pageviews
通过上面的指令,pageviews就会增加1了,加1可以很简单的解决了,那么如果要+2呢?执行两次INCR吗?直接用INCRBY命令就行啦。那么,我们可以用下面的指令
INCRBY userid:pageviews 2
除了INCR命令外,这个场景中还有可能会使用get/set/del/incr/decr/incrby/decrby
等命令,实际使用还需要结合场景的需要。
用法很简单,思考一下,我们如果不用redis,直接在代码里用一个变量存储,或者,直接把统计数据直接写入到MySQL不可以吗?在并发量小的时候,没有问题,但并发量大了,整个方案就不可用了。
我们先来说说直接在代码里面用一个变量存储网页访问次数,假设我们的服务有多个机器,那么就没办法保证每台服务器上存储的某个用户的网页次数的数据是一致的,这个方案直接毙掉。
而存储在MySQL中,网站访问次数是读写操作非常频繁的,高并发情况下,MySQL完全没办法承受压力。
所以这种场景下, 用Redis是最佳的选择,Redis的指令执行是单进程单线程,完全无锁,同时,Redis只需要对内存进行操作,因此操作非常快。
缓存热点数据
缓存数据是Redis最常用的场景,我们来看看实际的场景:
在一个直播页面,每次打开都需要展示直播的标题、直播描述等信息。直播的标题、直播描述等信息这些是直播的基础信息,对用户而言都是一样的,因此我们可以把这些数据存到redis中,使用redis加速。
直播的数据可能是下面的构造
{
"title": "直播标题",
"description": "测试的直播标题"
}
我们只需要将它作为一个字符串,存储到redis中即可,可以使用的命令set/get
在此处,我们要注意个小细节,数据的更新操作和缓存穿透问题。
分布式session
这种也是很常见的使用功能,我们来看看实际的场景:
智能客服估计大家都有接触过,比如我们在京东买东西,想了解下商品的一些其他信息,点击进客服的时,这时候,可能弹出的是一个机器人,我们通过和机器人对话,慢慢的了解到我们想要了解的信息了。
机器人怎么知道我们前面说的是内容呢?这里其实是有一个session的概念的。这个session记录了我们和机器人说的话,以及机器人的回答。机器人的回答都是根据这个session来判断的。
对于京东这种大厂来说,每天通过机器人的解决问题的人非常多,所以为了服务好这批人,机器人后台部署了多台的服务器。对于一个用户来说,他每一次提问都可能会落到不同的服务器上,为了让所有的机器都能认识这个session,就必须要用redis存储session。
Hash使用场景
假设我们在开发一个在线电商平台,需要存储和管理用户的个人资料信息。每个用户都有一组属性,比如用户名、电子邮件、密码哈希、联系地址和会员积分等。在这个场景中,可以使用Redis的hash数据结构来高效地存储和访问每个用户的资料。
例如,你可以为每个用户创建一个hash,hash的名字可以是user:{userId},其中{userId}是用户的唯一标识符。然后,你可以使用用户的各种属性作为hash的字段。
下面是如何使用Redis命令实现这个场景:
HSET user:1001 username "johndoe" email "john@example.com" password_hash "somehashedpassword" address "123 Main St" points 100
读用户的某个字段
HMGET user:1001 email address
上面的情况,把这些数据封装成一个redis,似乎也是可行的,那么为什么要用hash呢?
使用字符串类型加上JSON来存储对象数据时,如果需要频繁更新对象的某个属性,这种方法会显得不够高效和灵活。每次属性变化时,都必须重新序列化整个对象并将其作为一个整体存储,这不仅增加了处理的复杂性,还可能影响性能。相比之下,Redis的hash类型为修改对象的单个属性提供了一个更加优雅的解决方案。在hash结构中,你可以直接针对任何特定属性进行更新,无需对整个对象进行序列化或赋值,大幅减少了数据处理的负担。例如,商品的价格、销量、关注数量和评价数量这类经常变动的属性,就非常适合使用hash类型来存储。这样,当这些属性发生变化时,你只需简单地更新它们对应的字段即可,使得整个过程更加高效和响应迅速。
在真实使用的时候,还是需要结合我们的业务场景进行综合的评估。
List的使用场景
redis的list是一个有序的,可以有重复元素的列表,我们用下面的场景来说明List的用法。
排行榜应该都是很常见的应用场景,比如QQ音乐的周榜
每周都可以会离线计算一次榜单,将榜单存入到list中,lrange
可以分页查询数据,接口查询时,根据page和size,使用lrange
命令就可以分页查询榜单数据了。
在这个场景里,是一周计算一次榜单,那么,如果是实时榜单可以吗?对于list而言,实时榜单还真有点困难。
那么,如果我们想做实时榜单怎么办呢?用sorted set
Sorted Set的使用场景
Sorted Set特点是有序,无重复值。sorted set每个元素都会关联一个score属性,redis正是通过score来为集合中的成员进行从小到大的排序。
前面我们有提到过使用redis的list作为周榜单,但是作为实时榜单还是比较吃力的。用Sorted Set作为实时榜单就轻而易举了。
我们来看看命令是怎么实现的
# 添加榜单数据
ZADD leaderboard 100 user1
ZADD leaderboard 200 user2
使用 ZRANGE
或 ZREVRANGE
获取榜单上的成员及其分数,可以指定返回的排名区间。
ZRANGE leaderboard 0 -1 WITHSCORES
只需要两个命令就完成了实时榜单的功能,看起来很简单的。
好了,今天的分享就到这里啦!
本文由mdnice多平台发布