本文介绍: 一、Redis为什么快?二、Redis合适的应用场景 三、Redis为什么6.0之前不支持多线程 四、Redis为什么6.0之后引入多线程 五、Redis有哪些高级功能 六、为什么需要使用Redis 七、Redis的事务 八、Redis的过期策略以及内存淘汰机制 九、什么是缓存穿透如何避免? 十、什么是缓存雪崩如何避免? 十一、Redis如何设计分布式锁 十二、什么是bigkey?会有什么影响? 十三、Redis如何解决key冲突 十四、怎么提高换成命中率 十五、Redis持久方式哪些方式?

文章目录

一、Redis为什么快?

1、纯内存访问

相比查询数据库访问磁盘)要快很多

2、单线程,避免上下文切换

内部执行命令为单线程,避免上下文切换带来的CPU开销

3、渐进式ReHash缓存时间

(1)渐进式ReHash

Redis使用全局哈希表来保存所有键值对,

哈希表相当于一个数组,数组每个元素称为一个哈系桶,每个哈系桶中保存了键值对的数据

在这里插入图片描述

数据增加到一定阈值,数组扩容会导致数据发生移动,此时访问会发生阻塞

渐进式ReHash:把一次性大量拷贝(数组移动)的开销,分摊到多次处理请求过程中。

Redis默认使用两种全局哈希表,开始插入数据默认使用哈希表1,此时哈希表2并没有被分配空间。随着数据逐步增多,开始执行ReHash

  1. 哈希表2分配更大的空间
  2. 哈希表1中的数据重新映射拷贝到哈希表2中
  3. 释放哈希表1的空间

在这里插入图片描述

(2)缓存时间戳:

业务中需要用到时间戳时,一般会使用System.currentTimeMillis()或者New Date()等方式获取系统的毫秒时间戳,每一次获取都是一次系统调用(需要调用操作系统对应函数,涉及上下文切换),相对比较耗时。

作为单线程的Redis承受不起,因此它由一个定时任务,每毫秒更新一次缓存获取时间都是从缓存中直接拿。

二、Redis合适的应用场景

常用基本数据类型(5种)

名称 英文 作用域
字符串 String 缓存计数器分布式Session
哈希 Hash 存放对象
列表 list 消息队列文章列表
集合 set 标签随机数、社交图谱
有序集合 ZSET 排行榜
Bitmaps Bitmaps 布隆过滤器
HyperLogLog HyperLogLog UV

1、字符串(String)

命令时间复杂度

字符串这些命令中除了delmsetmget支持多个键的批量操作时间复杂度和键的个数相关,为O(n),getrange字符串长度相关,也是O(n),其余的命令基本上都是O(1)的时间复杂度,在速度上还是非常快的。

(1)缓存

具有支撑高并发特性,能起到加速读写的作用,降低后端压力

(2)计数器

实现快速计数查询缓存功能,同时数据可以异步落地到其他数据源

(3)分布式会话共享Session)

问题:如果一个分布式Web服务用户的Session信息保存在各自服务器中,出于负载均衡的考虑,分布式服务会将用户访问均衡到不同服务器上,用户刷新一次访问,可能会发现需要重新登录

解决方案:使用Redis将用户的Session进行集中管理,这种情况下只要保证Redis是高可用和扩展性的,每次用户更新或查询登录信息都直接从Redis集中获取

2、哈希(Hash

用于存放对象,相较于String类型存储对象时效率开发效率更高。

3、列表list

用来存储多个有序字符串

(1)消息队列

lpush+brpop命令组合即可实现阻塞队列,生产环境客户端使用lpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式的”抢“列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性

(2)文章列表

每个用户有属于自己的文章列表,现需要分页展示文章列表。此时可以考虑使用列表,有序,且支持按照索引范围获取元素

还可实现其他数据结构

img

4、集合set

(1)标签tag

例如一个用户可能对娱乐、体育感兴趣,另一个用户可能对历史、新闻感兴趣,这些兴趣点就是标签通过这些数据可以得到喜欢同一个标签的人,这些数据对于用户体验以及增强用户粘度比较重要。

(2)随机数(抽奖活动)
(3)社交图谱

5、有序集合(ZSET)

(1)排行榜

维度时间、浏览量、获赞数等等。

Redis高级数据结构

6、Bitmaps

可以实现对位的操作,单独提供了一套命令,可以想象成以位为单位的数组,数组下标叫做偏移量。

在这里插入图片描述

(1)布隆过滤器

在这里插入图片描述

7、HyperLogLog

(1)UV

统计每个网页每天的UC数据,HyperLogLog提供不精确的去重计数方案,误差0.81%

在这里插入图片描述

三、Redis为什么6.0之前不支持多线程

1、Redis的瓶颈不是CPU,受制于内存网络

存储于内存,快速读写网络开销大

2、提高Redis性能,Pipeline(命令批量

每秒100万个请求包装进Pipeline

3、单线程,内部维护成本相对较低,不需要管理多线程安全

命令执行顺序不确定性,读写并发问题

4、多线程(线程切换、加锁/解锁、导致死锁问题

5、惰性Rehash(渐进式)减少阻塞

一般的公司,单线程Redis就够了。

四、Redis为什么6.0之后引入多线程

1、小数据包。数据-》内存 响应时间 100ns 8w-10wQPS(极限)

2、针对大的公司,需要更大的QPS,IO的多线程(内部执行命令还是单线程)

3、为什么不采用分布式架构—很大的缺点。

服务器数量多,维护成本高。Redis命令 不适用 需要数据分区,无法解决点数据读写的问题

数据倾斜、重新分配、扩容、缩容,更加复杂

本质:多线程任务 分摊到Redis 同步IO中,读写负载。

五、Redis有哪些高级功能

(1)慢查询

快速定位系统中的慢操作监测发生时间、耗时、命令的详细信息

(2)Pipeline

在这里插入图片描述

(3)watch命令:

确保事务中的key没有被其他客户端修改过,才执行事务,否则不执行(类似于乐观锁)。

(4)Redis+Lua语言实现限流

在这里插入图片描述

(5)分布式

首先需要Redis有互斥的能力,可以使用SETNX命令,(即如果key存在,才会设置它的值,否则什么也不做。两个客户进程可以执行这个命令,达到互斥,就可以实现一个分布式锁。

锁的过期时间不好计算

在这里插入图片描述

解决方案:分布式锁加入看门狗

加锁时,先设置一个过期时间,然后开启**“守护线程”**,定时检测这个锁的失效时间,如果快要过期了,操作共享资源还未完成,则自动对锁进行续期,重新设置过期时间。

(6)高并发高可用

主从复制:

提供了复制功能实现了相同数据的多个Redis副本每个节点可以对应多个从节点复制数据流只能由主节点复制到从节点

在这里插入图片描述
在这里插入图片描述

(7)哨兵:Redis Sentinel

背景主从复制模式下,主节点故障,需要人工将从节点晋升为主节点。

2,8版本开始提供哨兵架构解决问题

主从复制问题

六、为什么需要使用Redis

1、高性能

Mysql磁盘)毫秒级

Redis(内存)微秒级

更新策略项目启动全量同步:热点数

2、高并发

Mysql 并发量:1000/s

Redis 并发量:100000/s

集群架构

在这里插入图片描述

七、Redis的事务

在这里插入图片描述

回滚机制上,Redis只能对基本语法错误进行判断运行错误无法回滚

八、Redis的过期策略以及内存淘汰机制

1、内存淘汰机制

总结:定期删除集中处理,惰性删除是零散处理

2、过期策略

3、缓存淘汰算法

当Redis内存超出物理内存限制时,内存数据开始和磁盘产生频繁的交换,此时性能会急剧下降。

通过maxmemory参数设置最大使用内存。

当内存超出时,Redis提供了集中策略来决定如何腾出新空间

九、什么是缓存穿透如何避免?

布隆过滤器应用

在这里插入图片描述

在这里插入图片描述

十、什么是缓存雪崩?如何避免?

原因:

1、Redis失效、宕机(故障
2、Redis大量key的ttl过期
  • ttl(过期时间)岔开,增加随机值,避免同一时间全部失效。

在这里插入图片描述

十一、Redis如何设计分布式锁

1、概念

  • 锁:同一时间只允许一个线程或者一个应用程序进入执行
  • 分布式锁:必须要求Redis有【互斥】能力,可以使用SETNX命令:即key不存在了才会设置它的值,否则什么也不做。

2、问题

十二、什么是bigkey?会有什么影响

1、概念

key对应的value所占内存空间较大

例如一个字符类型value最大存到512M,一个列表类型value最大可以存储2的32次方-1个元素。

2、字符串类型

体现在单个value特别大,一般认为超过10kb就是bigkey,和具体OPS相关(不同系统不同并发)。

3、非字符类型

哈希、列表、集合、有序集合,体现在元素个数过多。

4、危害:
5、解决方案value拆分

十三、Redis如何解决key冲突

1、业务隔离

2、key的设计

业务模块+系统名称+关键(id),针对用户可以加入(userid

3、分布式锁

场景:多个客户端并发写key

客户端拿到锁,才能进行操作,避免多个客户端竞争该key

4、时间戳

key拼接时间戳,根据时间戳保证多个客户端的业务执行顺序

十四、怎么提高换成命中率

1、提前加载

2、增加缓存的存储空间,增加缓存的数据

3、调整缓存的存储类型

例:对象通过Hash存储,而不用String。

根据业务做适当调整。

4、调整缓存的存储类型

十五、Redis持久化方式有哪些方式?有什么区别

1、持久化:

将数据写往磁盘,可以有效避免因进程退出造成的数据丢失,下次重启时利用之前持久化的文件恢复数据。

2、RDB(Redis DataBse):

当前数据生成快照(内存中的数据在某一时刻的状态记录保存硬盘过程

缺点:两次快照有时间间隔

3、AOF:

已独立日志的方式记录每次写命令,重启时重新执行AOF文件中的命令恢复数据。

缺点:性能较差。

4、生产环境中一般采用混合两者的方式

如果执行bgrewriteaof命令,将内存中已有的数据以二进制格式存放在AOF文件中(模拟RDB),后续命令亦然采用AOF追加方式。

在这里插入图片描述

十六、为什么Redis需要把所有数据放到内存中?

1、内存访问与磁盘访问的差距:

在这里插入图片描述

  • 几乎是10倍以上,如果不是顺序读取而是随机读取效率会相差更大
  • 同时还有CPU上下文切换的开销
2、Redis通过异步,持久化将数据写入磁盘
3、随着技术的发展,硬件上来说内存也越来越便宜
4、默认情况下,哪怕Redis内存不够了,也不会发生宕机,而是只可读不能写(Noeviction策略)
5、通过内存淘汰策略,确保整体服务正常运行

十七、如何保证缓存与数据库双写一致性

1、新增数据类

新增数据时,数据会直接写入数据库,不用对缓存做任何操作;此时缓存没有新增数据,而数据库中是最新值。

2、更新缓存类
(1)先更新缓存,在更新DB(一般不考虑)

原因:缓存更新成功,更新数据库时出现异常,会导致数据源与缓存数据完全不一致,而且很难察觉,因为缓存中的数据一直都存在。

(2)先更新DB,在更新缓存(一般不考虑)

原因:数据库更新成功了,缓存更新失败了,同样会导致数据源与缓存数据完全不一致,也很难察觉。

3、删除缓存
(3)先删除缓存,后更新DB
问题

两个请求:A(更新)和B(查询)

A -> 删除缓存中的数据 -> 更新数据库

B -> 查询缓存为空 -> 查询数据库 -> 补录到缓存

A -> 还未更新成功/事务还未提交,B -> 查询到的其实是数据库旧值

解决方案

这个休眠的时间需要评估项目的读数据业务逻辑的耗时,确保请求结束时,写请求可以删除读请求造成的缓存脏数据。

(4)先更新DB,后删除缓存

查询:先读缓存 -> 缓存没有就读数据库 -> 取出数据放入缓存 -> 同时返回响应

更新:先更新数据库 -> 删除缓存

4、如何选择

一般线上更多偏向于删除缓存类操作(容易避免问题

原因:

  • 删除缓存比在DB中要快,所以一般先更新DB,后删除缓存
  • 问题只会出现在查询比删除慢的情况,出现率相对最少
  • 同时延迟双删可以有效避免缓存不一致情况。

在这里插入图片描述

代码实现延迟双删
redis.deykey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)

十八、Redis集群方案

1、分布式解决方案 :Redis Cluster

3.0版本推出

场景:单机内存、并发、流量等瓶颈

方案:
(1)客户分区

优点:分区逻辑可控

缺点:需要处理数据路由、高可用、故障转移等问题

(2)代理方案:

优点:简化客户端分布式逻辑升级维护便利

缺点:加重架构部署复杂度和性能损耗

2、虚拟分区(0~16383)

在这里插入图片描述

主节点数基本不可能超过1000个,节点连接需要不断发送ping/pong命令,消耗网络带宽

3、集群功能限制

(1)key批量操作支持有限:mset、mget仅支持相同slot值的key。

(2)key事务操作支持有限:仅支持在同一节点上的事务操作。

(3)key作为数据分区的最小颗粒度,不允许大的键值对(hashlist映射在不同节点。

(4)不支持多数据库空间。单机为0-15(16个),集群模式仅能使用db0。

(5)复制结构仅支持一层,节点只能复制到主节点,不支持嵌套树状复制结构

4、搭建集群

方式:

(1)Redis协议手工搭建

(2)5.0之前有ruby语言脚本搭建

(3)5.0之后搭建功能合并rediscli

点数至少奇数点个,官方推荐三主三从。

十九、Redis集群方案什么情况下会导致整个集群不可用?

A、B、C三个节点集群,B节点失败(主故障,且没有替代方案)整个集群都是不可用的。

集群不可用判定:

保护措施:默认情况下当16384个槽点任何一个没有指派到节点时,整个集群不可用。

主节点下线->故障发现->自动完成转移期间,整个集群为不可用状态

可用通过设置clusterrequirefullcoverage配置no:主节点故障时,不影响其他主节点的可用性

二十、Redis集群会有写操作丢失吗?为什么?

Redis无法保证数据的强一致性

一般只能向主节点写入数据,再异步同步到子节点

此时如果响应客户端后还未异步同步成功时,主节点宕机了,子节点升至主节点,此时就会出现写入操作丢失

二十一、Redis常见性能问题和解决方案

1、持久化 性能问题

早期仅支持全量复制->部分复制(一台机器性能开销过大)

因此开始配置主从 :主节点不再做持久化而是交给从节点来做

2、数据比较重要,开启AOF。策略最好配置每秒同步。
3、主从复制 流畅,建议同一个局域网内操作,负责网络开销过大
4、尽量避免主库压力过大,增加从库
5、主从复制 尽量不要使用网状结构线性结构

二十二、热点数据和冷数据

1、热数据

访问频次较高,考虑使用缓存Redis

地图信息

点赞数、收藏数、分享数(不断变化)同步Redis

数据更新之前至少读取2次才能放缓存

2、冷数据

访问频次少

不需要放缓存

二十三、什么情况下可能会导致Redis阻塞

1、客户端阻塞

命令执行时间过长: keys* Hgetall smembers 时间复杂度O(N)

2、BIGkey删除

需要释放大量占用内存 zset(100万的元素 删除大概需要2s)

3、清空

flushdb flushall 涉及删除所有键值对

4、AOF日志同步写,记录AOF日志

大量写的操作

1一个同步写磁盘操作大概耗时1~2ms

5、从库 加载RDB文件

RDB文件过大

6、Redis尽量部署在独立的服务器中

二十四、线上Redis响应处理思路

原文地址:https://blog.csdn.net/Zyw907155124/article/details/129830935

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_12415.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注