redis是什么?看着一篇就够了

news2024/9/24 19:25:05

        目录

介绍一下 redis 数据库?

redis数据类型与应用场景

redis 为什么更快?

redis 怎么实现持久化的?

AOF 日志是如何实现的?

RDB 快照是如何实现的呢?

混合持久化

redis 单线程在多核机器里使用会不会浪费机器资源?

redis 执行命令还是单线程,那如何利用多核心来提升性能?

redis 缓存穿透、缓存击穿、缓存雪崩是什么?怎么解决?

缓存雪崩

解决方法

缓存击穿

解决方案:

缓存穿透

解决方案

怎么用 redis 分布式锁?

如何设计秒杀场景处理高并发以及超卖现象?

利用分布式锁

利用分布式锁 + 分段缓存

利用 redis 的 incr、decr 的原子性 + 异步队列

如果对热点数据设置过期时间,活动结束后删除可能会阻塞主线程,怎么解决?

Redis 内存淘汰策略


介绍一下 redis 数据库?

Redis 是一种基于内存的非关系型数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。 Redis 提供了多种数据类型来支持不同的业务场景,比如 String(字符串)、Hash(哈希)、 List (列表)、Set(集合)、Zset(有序集合)、Bitmaps(位图)、HyperLogLog(基数统计)、GEO (地理信息)、Stream(流),并且对数据类型的操作都是原子性的,因为执行命令由单线程负责的,不存在并发竞争的问题。 除此之外,Redis 还支持事务 、持久化、Lua 脚本、多种集群方案(主从复制模式、哨兵模式、切片机群模式)、发布/订阅模式,内存淘汰机制、过期删除机制等等。

redis数据类型与应用场景

Redis 常见数据类型和应用场景 | 小林coding (xiaolincoding.com)

Redis 的应用场景包括:缓存系统(“热点”数据:高频读、低频写)、计数器、消息队列系统、排行榜、社交网络和实时系统

redis 为什么更快?

官方使用基准测试的结果是,单线程的 Redis 吞吐量可以达到 10W/ 每秒,如下图所示:

之所以 Redis 采用单线程(网络 I/O 和执行命令)那么快,有如下几个原因:

• Redis 的大部分操作 都在内存中完成 ,并且采用了高效的数据结构,因此 Redis 瓶颈可能是机器的内存或者网络带宽,而并非 CPU,既然 CPU 不是瓶颈,那么自然就采用单线程的解决方案。

• Redis 采用单线程模型可以避免了多线程之间的竞争 ,省去了多线程切换带来的时间和性能上的开销,而且也不会导致死锁问题。

• Redis 采用了 I/O 多路复用机制 处理大量的客户端 Socket 请求,IO 多路复用机制是指一 个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。简单来说,在 Redis 只运 行单线程的情况下,该机制允许内核中,同时存在多个监听 Socket 和已连接 Socket。内 核会一直监听这些 Socket 上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。

redis 怎么实现持久化的?

Redis 的读写操作都是在内存中,所以 Redis 性能才会高,但是当 Redis 重启后,内存中的数 据就会丢失,那为了保证内存中的数据不会丢失,Redis 实现了数据持久化的机制,这个机制会把数据存储到磁盘,这样在 Redis 重启就能够从磁盘中恢复原有的数据。 Redis 共有两种数据持久化的方式:

AOF 日志 :每执行一条写操作命令,就把该命令以追加的方式写入到一个文件里;

RDB 快照 :将某一时刻的内存数据,以二进制的方式写入磁盘;

AOF 日志是如何实现的?

Redis 在执行完一条写操作命令后,就会把该命令以追加的方式写入到一个文件里,然后 Redis 重启时,会读取该文件记录的命令,然后逐一执行命令的方式来进行数据恢复。

我这里以「_set name xiaolin_」命令作为例子,Redis 执行了这条命令后,记录在 AOF 日 志里的内容如下图:

Redis 提供了 3 种写回硬盘的策略, 在 Redis.conf 配置文件中的 appendfsync 配置项可以 有以下 3 种参数可填:

• Always ,这个单词的意思是「总是」,所以它的意思是每次写操作命令执行完后,同步将 AOF 日志数据写回硬盘;

• Everysec ,这个单词的意思是「每秒」,所以它的意思是每次写操作命令执行完后,先将 命令写入到 AOF 文件的内核缓冲区,然后每隔一秒将缓冲区里的内容写回到硬盘;

• No ,意味着不由 Redis 控制写回硬盘的时机,转交给操作系统控制写回的时机,也就是每 次写操作命令执行完后,先将命令写入到 AOF 文件的内核缓冲区,再由操作系统决定何时 将缓冲区内容写回硬盘。

我也把这 3 个写回策略的优缺点总结成了一张表格:

RDB 快照是如何实现的呢?

因为 AOF 日志记录的是操作命令,不是实际的数据,所以用 AOF 方法做故障恢复时,需要全 量把日志都执行一遍,一旦 AOF 日志非常多,势必会造成 Redis 的恢复操作缓慢。为了解决 这个问题,Redis 增加了 RDB 快照。所谓的快照,就是记录某一个瞬间东西,比如当我们给 风景拍照时,那一个瞬间的画面和信息就记录到了一张照片。所以,RDB 快照就是记录某一个 瞬间的内存数据,记录的是实际数据,而 AOF 文件记录的是命令操作的日志,而不是实际的 数据。因此在 Redis 恢复数据时, RDB 恢复数据的效率会比 AOF 高些,因为直接将 RDB 文 件读入内存就可以,不需要像 AOF 那样还需要额外执行操作命令的步骤才能恢复数据。 Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave,他们的区别就在于是否在 「主线程」里执行:

• 执行了 save 命令,就会在主线程生成 RDB 文件,由于和执行操作命令在同一个线程,所 以如果写入 RDB 文件的时间太长, 会阻塞主线程;

• 执行了 bgsave 命令,会创建一个子进程来生成 RDB 文件,这样可以 避免主线程的阻塞;

混合持久化

在 Redis 4.0 提出了混合持久化。如果想要开启混合持久化功能,可以在 Redis 配置文件将下 面这个配置项设置成 yes:

aof-use-rdb-preamble yes

混合持久化是工作在 AOF 日志重写过程。当开启了混合持久化时,在 AOF 重写日志时, fork 出来的重写子进程会先将与主线程共享的内存数据以 RDB 方式写入到 AOF 文件,然后 主线程处理的操作命令会被记录在重写缓冲区里,重写缓冲区里的增量命令会以 AOF 方式写 入到 AOF 文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换 旧的的 AOF 文件。也就是说,使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量 数据,后半部分是 AOF 格式的增量数据。

这样的好处在于,重启 Redis 加载数据的时候,由于前半部分是 RDB 内容,这样加载的时候速度会很快。

redis 单线程在多核机器里使用会不会浪费机器资源?

虽然 Redis 的主要工作(网络 I/O 和执行命令)一直是单线程模型,但是在 Redis 6.0 版本之 后,也采用了多个 I/O 线程来处理网络请求,这是因为随着网络硬件的性能提升,Redis 的性 能瓶颈有时会出现在网络 I/O 的处理上。

所以为了提高网络 I/O 的并行度,Redis 6.0 对于网络 I/O 采用多线程来处理。但是对于命令 的执行,Redis 仍然使用单线程来处理。

Redis 官方表示,Redis 6.0 版本引入的多线程 I/O 特性对性能提升至少是一倍以上。

redis 执行命令还是单线程,那如何利用多核心来提升性能?

可以在系统部署多个 redis docker 容器来处理,达到充分利用 cpu 多核心的效果

redis 缓存穿透、缓存击穿、缓存雪崩是什么?怎么解决?

缓存雪崩

当大量缓存数据在同一时间过期或者 Redis 故障宕机时,如果此时有大量的用户请求,都无法 在 Redis 中处理,于是全部请求都直接访问数据库,从而导致数据库的压力增加,严重的会造 成数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃。

解决方法

大量数据同时过期

◦ 均匀设置过期时间 :避免将大量的数据设置成同一个过期时间。

◦ 互斥锁 :当业务线程在处理用户请求时,如果发现访问的数据不在 Redis 里,就加个 互斥锁,保证同一时间内只有一个请求来构建缓存。未能获取互斥锁的请求等待锁释放 后重新读取缓存,或者返回空值或者默认值。

◦ 双 key 策略 :使用两个 key,一个是主 key,设置过期时间,一个是备 key,不会设置 过期,key 不一样,但是 value 值是一样。当业务线程访问不到主 key 的缓存数据时, 就直接返回备 key 的缓存数据,然后在更新缓存的时候,同时更新主 key 和备 key 的数 据。

◦ 后台更新缓存 :业务线程不再负责更新缓存,缓存也不设置有效期,而是让缓存“永久 有效”,并将更新缓存的工作交由后台线程定时更新。

Redis 故障宕机

◦ 服务熔断或请求限流机制:启动 服务熔断 机制, 暂停业务应用对缓存服务的访问,直 接返回错误 ,所以不用再继续访问数据库,保证数据库系统的正常运行,等到 Redis 恢复正常后,再允许业务应用访问缓存服务。服务熔断机制是保护数据库的正常允许, 但是暂停了业务应用访问缓存服系统,全部业务都无法正常工作。也可以启用 请求限流 机制, 只将少部分请求发送到数据库进行处理,再多的请求就在入口直接拒绝服务。

◦ 构建高可靠集群:通过 主从节点的方式构建 Redis 缓存高可靠集群 。如果 Redis 缓存 的主节点故障宕机,从节点可以切换成为主节点,继续提供缓存服务,避免了由于 Redis 故障宕机而导致的缓存雪崩问题。

缓存击穿

如果缓存中的某个热点数据过期了,此时大量的请求访问了该热点数据,就无法从缓存中读 取,直接访问数据库,数据库很容易就被高并发的请求冲垮。

解决方案:

• 互斥锁方案 :保证同一时间只有一个业务线程更新缓存,未能获取互斥锁的请求,要么等 待锁释放后重新读取缓存,要么就返回空值或者默认值。

• 不给热点数据设置过期时间 :由后台异步更新缓存,或者在热点数据准备要过期前,提前 通知后台线程更新缓存以及重新设置过期时间。

缓存穿透

当用户访问的数据,既不在缓存中,也不在数据库中,导致请求在访问缓存时,发现缓存缺 失,再去访问数据库时,发现数据库中也没有要访问的数据,没办法构建缓存数据,来服务后 续的请求。那么当有大量这样的请求到来时,数据库的压力骤增,这就是缓存穿透的问题。

解决方案

• 非法请求的限制 :当有大量恶意请求访问不存在的数据的时候会发生缓存穿透,可以在 API 入口处判断求请求参数是否合理,请求参数是否含有非法值、请求字段是否存在,如果 判断出是恶意请求就直接返回错误,避免进一步访问缓存和数据库。

• 缓存空值或者默认值 :当线上业务发现缓存穿透的现象时,可以针对查询的数据,在缓存 中设置一个空值或者默认值,这样后续请求就可以从缓存中读取到空值或者默认值,返回给 应用,而不会继续查询数据库。

• 使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在 :可以 在写入数据库数据时,使用布隆过滤器做个标记,然后在用户请求到来时,业务线程确认缓 存失效后,可以通过查询布隆过滤器快速判断数据是否存在,如果不存在,就不用通过查询 数据库来判断数据是否存在。

怎么用 redis 分布式锁?

基于 Redis 节点实现分布式锁时,对于加锁操作,我们需要满足三个条件。

• 加锁包括了读取锁变量、检查锁变量值和设置锁变量值三个操作,但需要以原子操作的方式 完成,所以,我们使用 SET 命令带上 NX 选项来实现加锁;

• 锁变量需要设置过期时间,以免客户端拿到锁后发生异常,导致锁一直无法释放,所以,我 们在 SET 命令执行时加上 EX/PX 选项,设置其过期时间;

• 锁变量的值需要能区分来自不同客户端的加锁操作,以免在释放锁时,出现误释放操作,所 以,我们使用 SET 命令设置锁变量值时,每个客户端设置的值是一个唯一值,用于标识客 户端;

满足这三个条件的分布式命令如下:

SET lock_key unique_value NX PX 10000 

• lock_key 就是 key 键;

• unique_value 是客户端生成的唯一的标识,区分来自不同客户端的锁操作;

• NX 代表只在 lock_key 不存在时,才对 lock_key 进行设置操作;

• PX 10000 表示设置 lock_key 的过期时间为 10s,这是为了避免客户端发生异常而无法释 放锁。

而解锁的过程就是将 lock_key 键删除(del lock_key),但不能乱删,要保证执行操作的客 户端就是加锁的客户端。所以,解锁的时候,我们要先判断锁的 unique_value 是否为加锁客 户端,是的话,才将 lock_key 键删除。

可以看到,解锁是有两个操作,这时就需要 Lua 脚本来保证解锁的原子性,因为 Redis 在执 行 Lua 脚本时,可以以原子性的方式执行,保证了锁释放操作的原子性。

// 释放锁时,先比较 unique_value 是否相等,避免锁的误释放

if redis.call("get",KEYS[1]) == ARGV[1] then    

return redis.call("del",KEYS[1])

else    

return 0

end

这样一来,就通过使用 SET 命令和 Lua 脚本在 Redis 单节点上完成了分布式锁的加锁和解锁。

如何设计秒杀场景处理高并发以及超卖现象?

1. 在查询商品库存时加排他锁,执行如下语句:

select * from goods for where goods_id=? for update

在事务中线程 A 通过 语句给 goods_id 为具体的id的数据行上了锁。那么其他线程此时可以使用 select 语句读取数据,但是如 果也使用 select for update 语句加锁,或者使用 update,delete 都会阻塞,直到线程 A 将事 务提交(或者回滚),其他线程中的某个线程排在线程 A 后的线程才能获取到锁。

1. 更新数据库减库存的时候,进行库存限制条件

update goods set stock = stock - 1 where goods_id = ? and stock >0

这种通过数据库加锁来解决的方案,性能不是很好,在高并发的情况下,还可能存在因为获取 不到数据库连接或者因为超时等待而报错。

利用分布式锁

同一个锁 key,同一时间只能有一个客户端拿到锁,其他客户端会陷入无限的等待来尝试获取 那个锁,只有获取到锁的客户端才能执行下面的业务逻辑。这种方案的缺点是同一个商品在多用户同时下单的情况下,会基于分布式锁串行化处理,导致没法同时处理同一个商品的大量下单的请求。

利用分布式锁 + 分段缓存

把数据分成很多个段,每个段是一个单独的锁,所以多个线程过来并发修改数据的时候,可以 并发的修改不同段的数据 假设场景:假如你现在商品有 100 个库存,在 redis 存放 5 个库存 key,形如 :

key1=goods-01,value=20;
key2=goods-02,value=20;
key3=goods-03,value=20

用户下单时对用户 id 进行 %5 计算,看落在哪个 redis 的 key 上,就去取哪个,这样每次就能 够处理 5 个进程请求 这种方案可以解决同一个商品在多用户同时下单的情况,但有个坑需要解 决:当某段锁的库存不足,一定要实现自动释放锁然后换下一个分段库存再次尝试加锁处理, 此种方案复杂比较高。

利用 redis 的 incr、decr 的原子性 + 异步队列

实现思路

  1. 在系统初始化时,将商品的库存数量加载到 redis 缓存中
  2. 接收到秒杀请求时,在 redis 中进行预减库存(利用 redis decr 的原子性),当 redis 中 的库存不足时,直接返回秒杀失败,否则继续进行第 3 步;
  3. 将请求放入异步队列中,返回正在排队中;
  4. 服务端异步队列将请求出队(哪些请求可以出队,可以根据业务来判定,比如:判断对 应用户是否已经秒杀过对应商品,防止重复秒杀),出队成功的请求可以生成秒杀订单,减 少数据库库存(在扣减库存的 sql 如下,返回秒杀订单详情)
update goods set stock = stock - 1 where goods_id = ? and stock >0

        5.用户在客户端申请秒杀请求后,进行轮询,查看是否秒杀成功,秒杀成功则进入秒杀订单详情,否则秒杀失败

这种方案的缺点:由于是通过异步队列写入数据库中,可能存在数据不一致,其次引用多个组 件复杂度比较高

如果对热点数据设置过期时间,活动结束后删除可能会阻塞主线程,怎么解决?

可以使用 unlink 的方式来删除缓存,unlink 是异步删除数据,不会阻塞主线程。

Redis 内存淘汰策略

Redis 内存淘汰策略共有八种,这八种策略大体分为「不进行数据淘汰」和「进行数据淘汰」 两类策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2070863.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LABVIEW数据保存文件

这里推荐选用CSV文件?为什么? 下表是格式差异造成的容量差异。 具体原因,总结为以下两点: 首先,CSV文件能使用EXCEL打开,方便查阅和借助EXCEL工具进一步处理。 第二,相对来说,CSV…

Web自动化测试:selenium使用详解

🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 说到自动化测试,就不得不提大名鼎鼎的Selenium。Selenium 是如今最常用的自动化测试工具之一,支持快速开发自动化测试框架,…

深信服上半年亏损5.92亿,营收同比降低2.3亿

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

Qt:玩转QPainter序列二

前言 接着序列一开始序列二。 正文 继续先看源码,下面是分析 1. Q_FLAG(RenderHint) Q_FLAG是Qt宏,用于向Qt的元对象系统(Meta-Object System)注册枚举值,以便可以在Qt的元对象系统中使用这些枚举值。例如&#…

SD 卡无法读取?这十大方法助你轻松修复!

在我们的日常生活中,SD 卡被广泛应用于各种设备,如数码相机、手机、平板电脑等。然而,有时我们可能会遇到 SD 卡无法读取的情况,这让人十分苦恼。别担心,下面为你介绍多种修复 SD 卡无法读取问题的方法。 一、检查硬件…

如何知道当前网卡连接的下位机的IP,通过工具实现

要确定当前网卡连接的下位机的 IP 地址,可以使用以下几种工具和方法来实现。 1. 使用 arp-scan 工具 arp-scan 是一个强大的网络扫描工具,可以用于扫描网络上的设备并显示它们的 IP 和 MAC 地址。 安装 arp-scan: sudo apt update sudo a…

合宙LuatOS开发板使用说明——Air700ECQ

EVB-Air700ECQ-IO 开发板是合宙通信推出的基于 Air700ECQ 模组所开发的,包含电 源, SIM 卡,USB ,天 线, 全 IO 引 出的最 小硬 件系 统。以 方便 用户 在设 计前期 对 Air700ECQ 模块进行性能评估,功能调试…

AutoMapperSQL

AutoMapperSQL--Mybatis实用小工具:根据数据模型、数据访问接口自动生成 mysql、sql server、oracle 三种数据源类型的表脚本及mybatis接口类对应的mapper-xml文件。 1、指定数据访问接口 mapper interface 目录路径; 2、指定数据模型目录路径&#xff1…

机器学习-OpenCV运用(1)

文章目录 一、OpenCV介绍二、OpenCV运用1.读取保存图片2.读取视频3.图像切片 一、OpenCV介绍 OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库,它主要用于实时的图像处理和计算机视觉任务。虽然OpenCV本…

ARM架构与ARM内核

参考:https://blog.csdn.net/qq_34160841/article/details/105611131 到底什么是Cortex、ARMv8、arm架构、ARM指令集、soc?一文帮你梳理基础概念 认识ARM、Cortex-M内核,以及ARMv8-M架构 ARM架构 ARM的架构指的是ARM的指令集架构。ARM指令集…

基于WordPress搭建的写真网站整站打包代码,可直接运营

直接服务器整站源码数据库打包了。 这个包的资源非常多,也非常火爆,吸引力还是挺大的。用这个架设一个引流网站还是轻松的。 图片太多太敏感,就不在这里显示了,懂的都懂。 代码测试过了,运行是完全没问题的。已经好…

CSS学习【margin为负值】

目录 margin塌陷时合并规则 margin重叠概念 可能会发生的情况 外边距重叠计算规则 兄弟元素之间合并,都为负值 当“.box1”和“.box2”都未设置外间距时: 给“.box1”和“.box2”设置外间距后: 兄弟元素间合并,一正一负 …

深入解析SSRF和Redis未授权访问

深入解析SSRF和Redis未授权访问:漏洞分析与防御 在网络安全领域,服务器端请求伪造(SSRF) 和 Redis未授权访问 是两类常见且危险的安全漏洞。 1.2 SSRF攻击的利用 1.2.1 测试并确认SSRF漏洞 一个典型的例子是,当应用…

迭代器的失效问题

vector的插入与删除 我们首先举例说明vector插入和删除操作返回的是什么迭代器 void print(std::vector<int>& vec) {for(auto itvec.begin();it!vec.end();it)std::cout<<*it<<" ";std::cout<<std::endl; }void test() {/*初始化vect…

Simple RPC - 07 从零开始设计一个服务端(下)_RPC服务的实现

文章目录 PreRPC服务实现服务注册请求处理 设计&#xff1a; 请求分发机制 Pre Simple RPC - 01 框架原理及总体架构初探 Simple RPC - 02 通用高性能序列化和反序列化设计与实现 Simple RPC - 03 借助Netty实现异步网络通信 Simple RPC - 04 从零开始设计一个客户端&#…

【数据结构】堆主要的应用场景

1. 堆排序 所谓堆排序&#xff0c;就是在堆的基础上进行排序。 在讲解堆排序之前&#xff0c;让我们先来回顾一下堆的概念&#xff0c; 1.1 大根堆和小根堆 堆是一种完全二叉树&#xff0c;它有两种形式&#xff0c;一种是大根堆&#xff0c;另外一种是小根堆。 大根堆&…

2023年看过的电影和电视剧

2023年看过的电影 2023年12月21日&#xff1a;三大队 评价&#xff1a;感觉结尾不太突出&#xff0c;但是值得一看。 2023年10月02日&#xff1a;志愿军&#xff1a;雄兵出击 评价&#xff1a;感觉还行&#xff0c;场面还不错。但是记不得太多情节。 2023年08月31日&#xf…

如何将 Parallels Desktop 许可证密钥移至新的 Mac?

根据 Parallels 最终用户许可协议&#xff08;EULA&#xff09;的规定&#xff0c;您最多可以在一台设备上下载、安装和使用 Parallels Desktop 的一个原始副本。但是面对更换新机的用户&#xff0c;可以通过迁移的方式把 Parallels Desktop 许可证密钥移至新的 Mac&#xff0c…

跟《经济学人》学英文:2024年08月24日这期 What to make of America’s topsy-turvy economy

What to make of America’s topsy-turvy economy Don’t panic just yet topsy-turvy&#xff1a;颠倒的&#xff1b;混乱的&#xff1b;乱七八糟的&#xff1b; make of&#xff1a;理解&#xff1b;认为&#xff1b;看待 Make of: 这里的 “make of” 意思是如何理解或解释…

自来水厂供水监控的串口服务器应用

随着城市化进程的加快和人口的不断增长&#xff0c;自来水厂作为城市供水系统的核心组成部分&#xff0c;其稳定性和安全性对于城市的正常运行和居民的生活质量至关重要。传统的供水监控系统存在数据传输效率低、维护成本高、实时性差等问题&#xff0c;难以满足现代城市对供水…