共计 3482 个字符,预计需要花费 9 分钟才能阅读完成。
自动写代码机器人,免费开通
这篇文章将为大家详细讲解有关 Redis 在项目中的应用场景是什么,丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
相信对于绝大多数程序员来说,redis 中间件应该是大家非常熟悉的。但是对于工作中经常写业务代码的程序员来说,他们在实际工作中可能只是用到了 set value、get value 等操作,对于 redis 缺乏整体认识。
Redis 是什么?
Redis 是一个开源的底层使用 C 语言编写的 key-value 存储数据库。可用于缓存、事件发布订阅、高速队列等场景。而且支持丰富的数据类型:string(字符串)、hash(哈希)、list(列表)、set(无序集合)、zset(sorted set:有序集合)
Redis 在项目中的应用场景
1、缓存数据
最常用,对经常需要查询且变动不是很频繁的数据 常称作热点数据。
2、消息队列
相当于消息订阅系统,比如 ActiveMQ、RocketMQ。如果对数据有较高一致性要求时,还是建议使用 MQ)
3、计数器
比如统计点击率、点赞率,redis 具有原子性,可以避免并发问题
4、电商网站信息
大型电商平台初始化页面数据的缓存。比如去哪儿网购买机票的时候首页的价格和你点进去的价格会有差异。
5、热点数据
比如新闻网站实时热点、微博热搜等,需要频繁更新。总数据量比较大的时候直接从数据库查询会影响性能
给个爱的理由
在单节点服务器我们通常是这样的
随着企业的发展、业务的扩展。面对海量的数据,直接使用 MySql 会导致性能下降,数据的读写也会非常慢。于是我们就可以搭配缓存来处理海量数据。
于是现在我们是这样的:
上图只是简述了缓存的作用,当数据继续增大我们需要利用主从复制技术来达到读写分离
数据库层直接与缓存进行交互,如果缓存中有数据直接返回客户端,如果没有才会从 MySql 中去查询。从而减小了数据库的压力,提升了效率。
平时发布了一款新手机,会有抢购活动。同一时间段,服务端会收到很多的下单请求。
我们需要使用 redis 的原子操作来实现这个“单线程”。首先我们把库存存在一个列表中,假设有 10 件库存,就往列表中 push20 个数,这个数没有实际意义,仅仅只是代表 10 件库存。抢购开始后,每到来一个用户,就从列表中 pop 一个数,表示用户抢购成功。当列表为空时,表示已经被抢光了。因为列表的 pop 操作是原子的,即使有很多用户同时到达,也是依次执行的
题外话:还有的抢购是直接在前端页面限制请求,这些请求直接被前端拦截,并没有到后端服务器
Redis 为什么会这么快?
1、Redis 是纯内存操作,需要的时候需要我们手动持久化到硬盘中
2、Redis 是单线程,从而避开了多线程中上下文频繁切换的操作。
3、Redis 数据结构简单、对数据的操作也比较简单
4、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求
5、使用多路 I / O 复用模型,非阻塞 I /O
多路 I / O 复用: I/O 多路复用技术是为了解决进程或线程阻塞到某个 I/O 系统调用而出现的技术,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪,就是这个文件描述符进行读写操作之前),能够通知程序进行相应的读写操作
(学习视频分享:redis 视频教程)
Redis 数据类型的应用场景
前面提到了 Redis 支持五种丰富的数据类型,那么在不同场景下我们该怎么选择呢?
String
字符串是最常用的数据类型,他能够存储任何类型的字符串,当然也包括二进制、JSON 化的对象、甚至是 base64 编码之后的图片。在 Redis 中一个字符串最大的容量为 512MB,可以说是无所不能了。
Hash
常用作存储结构化数据、比如论坛系统中可以用来存储用户的 Id、昵称、头像、积分等信息。如果需要修改其中的信息,只需要通过 Key 取出 Value 进行反序列化修改某一项的值,再序列化存储到 Redis 中,Hash 结构存储,由于 Hash 结构会在单个 Hash 元素在不足一定数量时进行压缩存储,所以可以大量节约内存。这一点在 String 结构里是不存在的。
List
List 的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis 内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。另外,可以利用 lrange 命令,做基于 Redis 的分页功能,性能极佳,用户体验好。
Set
set 对外提供的功能与 list 类似是一个列表的功能,特殊之处在于 set 是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,这个时候就可以选择使用 set。
Sort Set
可以按照某个条件的权重进行排序,比如可以通过点击数做出排行榜的数据应用。
Redis 缓存的数据一致性
真正意义上来讲数据库的数据和缓存的数据是不可能一致的,数据分为最终一直和强一致两类。如果业务中对数据的要求必须强一直那么就不能使用缓存。缓存能做的只能保证数据的最终一致性。
我们能做的只能是尽可能的保证数据的一致性。不管是先删库再删缓存 还是 先删缓存再删库,都可能出现数据不一致的情况,因为读和写操作是并发的,我们没办法保证他们的先后顺序。具体应对策略还是要根据业务需求来定,这里就不赘述了。
Redis 的过期和内存淘汰
Redis 存储数据时我们可以设置他的过期时间。但是这个 key 是怎么删除的呢?
一开始我认为是定时删除,后来发现并不是这样,因为如果定时删除,需要一个定时器来不断的负责监控这个 key,虽然内存释放了,但是非常消耗 cpu 资源。
Redis 过期删除采用的是定期删除,默认是每 100ms 检测一次,遇到过期的 key 则进行删除,这里的检测并不是顺序检测,而是随机检测。那这样会不会有漏网之鱼?显然 Redis 也考虑到了这一点,当我们去读 / 写一个已经过期的 key 时,会触发 Redis 的惰性删除策略,直接回干掉过期的 key
内存淘汰是指用户存储的一部分 key 是可以被 Redis 自动的删除,从而会出现从缓存中查不到数据的情况。加入我们的服务器内存为 2G、但是随着业务的发展缓存的数据已经超过 2G 了。但是这并不影响我们程序的运行,因为操作系统的可见内存并不受物理内存的限制。物理内存不够用没关系,计算机会从硬盘中划出一片空间来作为虚拟内存。这就是 Redis 设计两种应用场景的初衷:缓存、持久存储
缓存击穿
缓存只是为了缓解数据库压力而添加的一层保护层,当从缓存中查询不到我们需要的数据就要去数据库中查询了。如果被黑客利用,频繁去访问缓存中没有的数据,那么缓存就失去了存在的意义,瞬间所有请求的压力都落在了数据库上,这样会导致数据库连接异常。
解决方案:
1、后台设置定时任务,主动的去更新缓存数据。这种方案容易理解,但是当 key 比较分散的时候,操作起来还是比较复杂的
2、分级缓存。比如设置两层缓存保护层,1 级缓存失效时间短,2 级缓存失效时间长。有请求过来优先从 1 级缓存中去查找,如果在 1 级缓存中没有找到相应数据,则对该线程进行加锁,这个线程再从数据库中取到数据,更新至 1 级和 2 级缓存。其他线程则直接从 2 级线程中获取
3、提供一个拦截机制,内部维护一系列合法的 key 值。当请求的 key 不合法时,直接返回。
缓存雪崩
缓存雪崩就是指缓存由于某些原因(比如 宕机、cache 服务挂了或者不响应)整体 crash 掉了,导致大量请求到达后端数据库,从而导致数据库崩溃,整个系统崩溃,发生灾难,也就是上面提到的缓存击穿。
如何避免雪崩:
1、给缓存加上一定区间内的随机生效时间,不同的 key 设置不同的失效时间,避免同一时间集体失效。
2、和缓存击穿解决方案类似,做二级缓存,原始缓存失效时从拷贝缓存中读取数据。
3、利用加锁或者队列方式避免过多请求同时对服务器进行读写操作。
结语:
Redis 的性能极高,读的速度是 110000 次 /s, 写的速度是 81000 次 /s,支持事务,支持备份,丰富的数据类型。
任何事情都是两面性,Redis 也是有缺点的:
1、由于是内存数据库,所以单台机器存储的数据量是有限的,需要开发者提前预估,需要及时删除不需要的数据。
2、当修改 Redis 的数据之后需要将持久化到硬盘的数据重新加入到内容中,时间比较久,这个时候 Redis 是无法正常运行的。
关于“Redis 在项目中的应用场景是什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
向 AI 问一下细节