Redis的使用场景有哪些?面试时随身携带!
Redis作为内存型非关系型数据库,在大型互联网公司、小工厂、大项目、小项目中几乎都会用到。为什么Redis如此受欢迎?至于问题,很多程序员只能看别人用,对Redis缺乏全面的了解。
Redis 使用场景
缓存
缓存现在几乎是所有中大型网站的必需品。明智地使用缓存不仅可以提高访问网站的速度,还可以显着减轻数据库的压力。 Redis提供了key过期功能和灵活的key淘汰策略。因此,现在很多缓存情况都会用到Redis。
评分
很多网站都有评分应用,比如京东每月销量榜、新品按时间排行等。 Redis提供的有序数据结构可以实现各种复杂的评估应用。
计数器
什么是计数器,比如电商网站的商品浏览量、视频网站的视频浏览量等。为了保证实时数据性能,每次浏览都必须+1。当并发量较高时,每次都请求数据库操作无疑是一种挑战和压力。 Redis提供的incr命令实现了计数器功能和内存操作,性能非常好,非常适合这些计数场景。
分布式会话
集群模式下,应用不多时,一般使用容器自带的会话复制功能就足够了。当应用数量增多、系统变得相对复杂时,一般会创建Redis等内存数据库。由于它是中央会话服务,因此会话不再由容器管理,而是由会话服务和内存数据库管理。
分布式锁
分布式技术在很多互联网公司都有使用。分布式技术带来的技术挑战是同一资源的并发访问,比如全局ID、库存减量、闪购等场景。小数据量的并发场景可以使用数据库悲观锁和乐观锁来实现。然而,在高并发情况下,使用数据库锁来控制资源的并发访问并不理想,这会显着影响数据库性能。可以使用Redis的setnx函数来编写分布式锁。如果设置返回值1,则表示获取锁成功。否则会导致获取锁失败。在实际应用中,还需要考虑更多的细节。
社交网络
喜欢、不喜欢、关注/关注、共同好友等。是社交网站的基本功能。社交网站的访问量通常比较大,传统类型的关系数据库不适合存储这类数据,Redis提供的哈希、集合等数据结构可以轻松实现这些功能。
最新列表
Redis 列表结构,LPUSH 可以在列表开头插入内容 ID 作为关键字,LTRIM 可以用来限制列表数量,所以在不查询列表的情况下列表永远是 N 个 ID最新列表,直接根据ID进入对应的内容页面即可。
消息系统
消息队列是大型网站必备的中间件,例如ActiveMQ、RabbitMQ、Kafka等流行的消息队列中间件。主要用于小批量实时业务的业务分离、去峰、异步处理。 Redis提供了发布/订阅和块队列功能,可以实现简单的消息队列系统。而且,它无法与专业的消息中间件相比。
使用方法
上面列出了不同的使用场景。这些场景无非就是对Redis数据类型的操作。您需要了解一些有关 Redis 数据类型的知识。在 Redis 中,这些是数据类型。
链、哈希、列表、集合、Zset、GEO、流、HyperLogLog、BitMap。
数据使用场景
字符串类型
字符串类型是类似于键值对的字符串类型。
我们一般使用String类型来存储很多产品、用户信息、分布式锁等应用场景。
存储产品数量。
set goods:count:1 1233 set goods:count:2 100
用户信息。
set user:1 "{"id":1, "name":"张三", "age": 12}" set user:2 "{"id":2, "name":"李四", "age": 12}"
分布式锁。
# 设置一个不存在的键名为id:1值为10, 过期时间为10秒。 127.0.0.1:6379> set id:1 10 ex 10 nx OK 127.0.0.1:6379> get id:1 "10" # 当前的键还未过期,在次设置则不会设置成功。 127.0.0.1:6379> set id:1 10 ex 10 nx (nil) # 当10秒之后去获取,当前的键则为空。 127.0.0.1:6379> get id:1 (nil)
使用Redis实现分布式锁原理。如果该密钥存在,则设置将失败。
哈希类型
哈希类型是一种类似于关系数据库结构的数据结构。有一个键名,键中存储的内容以键值对的形式存在。
利用哈希结构,我们可以用它来存储用户信息、对象信息等业务场景。
保存用户信息。
127.0.0.1:6379> hset user:1 id 1 name zhangsan age 12 sex 1 (integer) 4 127.0.0.1:6379> hset user:2 id 2 name lisi age 14 sex 0 (integer) 4 127.0.0.1:6379> hmget user:1 id name age sex 1) "1" 2) "zhangsan" 3) "12" 4) "1"
保存有关对象的信息。
127.0.0.1:6379> hset object:user id public-1 name private-zhangsan (integer) 2 127.0.0.1:6379> hmget object:uesr id name 1) (nil) 2) (nil) 127.0.0.1:6379> hget object:user id "public-1" 127.0.0.1:6379>
用户对象存储在这里。对象中有两个属性,即id和name。它们存储访问权限和属性绑定默认值。
列表类型
列表类型是列表类型的数据结构。使用键组织数据。
List一般用于队列、堆栈、秒杀等场景。
队列。
127.0.0.1:6379> lpush list:1 0 1 2 3 4 5 6 (integer) 7 127.0.0.1:6379> rpop list:1 1 1) "0" 127.0.0.1:6379> rpop list:1 1 1) "1" 127.0.0.1:6379> rpop list:1 1 1) "2"
使用列表来实现队列,因为队列遵循先进先出的特性。
水库。
127.0.0.1:6379> lpush list:1 3 4 5 6 (integer) 3 127.0.0.1:6379> lpop list:1 "6" 127.0.0.1:6379> lpop list:1 "5" 127.0.0.1:6379> lpop list:1 "4" 127.0.0.1:6379> lpop list:1 "3"
使用列表来实现队列,因为队列遵循“后进先出”的特性。
立即出售。
127.0.0.1:6379> lpush order:user 11 12 14 15 16 17 (integer) 6
在闪购场景中,我们可以将闪购成功的用户注册为队列中的第一个,后续的交易将根据队列中的数据进行处理。
集合类型
zet 是集合类型,该集合中的元素无用,不会重复。集合类型
一般可用于用户注册、网站访问统计、用户跟踪标签、好友推荐、猜价、随机数生成等业务场景。
某一天的用户注册状态。键
127.0.0.1:6379> sadd sign:2020-01-16 1 2 3 4 5 6 7 8 (integer) 8 127.0.0.1:6379> smembers sign:2020-01-16 1) "1" 2) "2" 3) "3" 4) "4" 5) "5" 6) "6" 7) "7" 8) "8"
代表特定日期,存储的值是登录用户的ID。
用户关注品牌。
127.0.0.1:6379> sadd user:1:friend 1 2 3 4 5 6 (integer) 6 127.0.0.1:6379> sadd user:2:friend 11 22 7 4 5 6 (integer) 6 127.0.0.1:6379> sinterstore user:relation user:1:friend user:2:friend (integer) 3 127.0.0.1:6379> smembers user:relation 1) "4" 2) "5" 3) "6"
用户 1 关注了 ID 为 1、2、3、4、5 和 6 的列。用户 2 关注了 ID 为 11、22、7、4、5 和 6 的列。这里,我们采用两个用户关注的列注意。
猜猜价格。
127.0.0.1:6379> spop user:2:friend 1 1) "5"
使用集合来实现价格小费主要利用给定类元素随机抛出的特性。 2 有序文件,即集合,也称为有序文件。
zset不仅可以用在set可以使用的场景,还可以用在排序、延迟队列等排序场景,比如未支付的订单多久过期。
登录排名。
127.0.0.1:6379> zadd goods:order 1610812987 1 (integer) 1 127.0.0.1:6379> zadd goods:order 1610812980 2 (integer) 1 127.0.0.1:6379> zadd goods:order 1610812950 3 (integer) 1 127.0.0.1:6379> zadd goods:order 1610814950 4 (integer) 1 127.0.0.1:6379> zcard goods:order (integer) 4 127.0.0.1:6379> zrangebyscore goods:order 1610812950 1610812987 1) "3" 2) "2" 3) "1"
以用户的登录时间作为排名分数,最后询问在指定范围内登录的用户的ID。
位图类型
位图在底层以二进制格式存储数据。在一些特定场景下,使用这种类型可以显着减少存储空间,因为存储的数据只能是0和1。为了更容易理解,这种数据格式可以理解为以数组。
通过该功能,该类型可以用于访问统计、注册统计等一些场景。
1个月的用户登录记录。
127.0.0.1:6379> setbit user:2020-01 0 1 (integer) 0 127.0.0.1:6379> setbit user:2020-01 1 1 (integer) 0 127.0.0.1:6379> setbit user:2020-01 2 1 (integer) 0 127.0.0.1:6379> bitcount user:2020-01 0 4 (integer) 3
统计显示,该用户本月仅登录4天。
统计某一天网站签到的次数。
127.0.0.1:6379> setbit site:2020-01-17 1 1 (integer) 0 127.0.0.1:6379> setbit site:2020-01-17 3 1 (integer) 0 127.0.0.1:6379> setbit site:2020-01-17 4 1 (integer) 0 127.0.0.1:6379> setbit site:2020-01-17 6 1 (integer) 0 127.0.0.1:6379> bitcount site:2020-01-17 0 100 (integer) 4 127.0.0.1:6379> getbit site:2020-01-17 5 (integer) 0
这里以用户ID作为补偿,登录名为1。可以统计具体访问的总次数,同时可以根据ID询问用户当前是否正在登录。如果根据offset重复设置该值,则不会重复添加,但Redis会返回1,表示当前存在。
统计一定时间段内登录的用户数量。
127.0.0.1:6379> setbit site:2020-01-18 6 1 (integer) 0 127.0.0.1:6379> setbit site:2020-01-18 4 1 (integer) 0 127.0.0.1:6379> setbit site:2020-01-18 7 1 (integer) 0 127.0.0.1:6379> bitop and continue:site site:2020-01-18 site:2020-01-17 (integer) 1
使用此场景是因为该数据类型可以计算多个键的交集(a)。同时可以取并(或)、或(或)、异或(异或)。
HypefLogLog 类型
HypefLogLog 类型在用法上与集合类型有些相似。这种类型实际上是一个字符串数据结构。使用这种类型的最大优点是减少了空间,但也存在一定的错误率。此类型也不允许具有相同键的重复元素。此类型还支持多个键值的串联。
该数据类型一般用于一些不需要精确计算的统计场景。
用户登录统计。
127.0.0.1:6379> pfadd 2020:01:sgin 1 2 3 4 5 6 7 8 (integer) 1 # 尝试重复添加 127.0.0.1:6379> pfadd 2020:02:sgin 1 2 3 4 5 6 7 8 (integer) 0 127.0.0.1:6379> pfadd 2020:02:sgin 9 (integer) 1 127.0.0.1:6379> pfadd 2020:02:sgin 10 (integer) 1 127.0.0.1:6379> pfadd 2020:02:sgin 11 (integer) 1 127.0.0.1:6379> pfcount 2020:02:sgin (integer) 11
GEO 类型
GEO 类型是一种基于地理信息的特征来存储地理信息的数据格式。可以用于距离计算、附近推荐等一些业务场景。
距离计算
127.0.0.1:6379> geoadd city:distance nx 121.32 42.36 beijing 121.20 38.56 shanghai 100.36 38.56 sichuan (integer) 3 127.0.0.1:6379> geopos city:distance beijing shanghai sichuan 1) 1) "121.32000178098678589" 2) "42.36000020595371751" 2) 1) "121.19999974966049194" 2) "38.55999947301710762" 3) 1) "100.3599974513053894" 2) "38.55999947301710762" # 计算出北京到上海的距离 127.0.0.1:6379> geodist city:distance beijing shanghai km "422.7819"
流类型
流类型是Redis 5.0版本之后添加的新数据结构。该数据结构主要用于消息队列场景。 Redis本身有Redis发布和订阅(pub/sub)来实现消息队列功能,但其缺点是消息无法存储。如果出现网络断开、Redis 中断等情况,消息将会被丢弃。
消息队列
# 添加消息队列 127.0.0.1:6379> xadd message * name zhangsan age 12 "1610873104343-0" 127.0.0.1:6379> xrange message - + 1) 1) "1610873104343-0" 2) 1) "name" 2) "zhangsan" 3) "age" 4) "12" # 获取消息队列 127.0.0.1:6379> xrevrange message + - count 1 1) 1) "1610873104343-0" 2) 1) "name" 2) "zhangsan" 3) "age" 4) "12"
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。