[缓存] - Redis

0.为什么要使用缓存?

用缓存,主要有两个用途:高性能、高并发。

1. 高性能

尽量使用短key

不要存过大的数据

避免使用keys *:使用SCAN,来代替

在存到Redis之前压缩数据

设置 key 有效期

选择回收策略(maxmemory-policy)

减少不必要的连接

限制redis的内存大小(防止swap,OOM)

slowLog

使用pipline批量操作数据

2. 高可用

2.1 单机版的高可用

数据持久化:AOF(WAL) & RDB

2.2 Replication-Sentinel模式

也就是哨兵模式。哨兵能对节点进行监控,提醒,自动故障迁移。

缺点:主从模式,切换需要时间,可能会丢数据,而且没有解决 master 写的压力;存储性能没办法横向扩展。

适用场景:缓存大小<10G时建议使用一主多从的哨兵模式。 从节点的数量,根据qps来扩展,比如10WQPS,可以有3-4个从节点(只能提高读操作的qps,写的qps不能扩展)。

架构图:

 2.3 Redis-Cluster模式

redis在3.0上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,也就是说每台 Redis 节点上存储不同的数据。

Gossip协议维护节点的元数据信息,进行节点间的信息同步。P2P去中心化的模式。最终一致性。

每个分区有一个master和若干slaver组成。

缺点:对于大型集群来说, 例如200 个使用 3.2.8 版本节点搭建的 Redis 集群,在没有任何客户端请求的情况下,每个节点仍然会产生 40Mb/s 的流量(gossip协议), 不建议使用官方的 Redis Cluster。

适用场景:如果系统的缓存大小<2000G, 主节点数<200个,建议使用Redis Cluster模式

2.4 Proxy模式

适用于主节点数量 > 200的情况下。有Codis Proxy和Twemproxy Proxy来年各种中间件模式。

数据分片算法:

(1)Codis 代理分片

(2)Twemproxy 代理分片

2.4.1 数据分片

(1)Range分片

常用在关系型数据库的设计。

比如:1到100个数字,要保存在3个节点上,按照顺序分区,把数据平均分配成三个片段

  • 1号到33号数据为 片段1

  • 34号到66号数据为 片段2

  • 67号到100号数据为 片段3

(2)节点取余分片

比如有100个数据,对每个数据进行hash运算之后,与节点数进行取余运算,根据余数不同保存在不同的节点上。

缺点:

当增加或减少节点时,原来节点中的80%的数据会进行迁移操作,对所有数据重新进行分片。

建议:

建议使用多倍扩容的方式,例如以前用3个节点保存数据,扩容为比以前多一倍的节点即6个节点来保存数据,这样只需要适移50%的数据。

数据迁移之后,第一次无法从缓存中读取数据,必须先从数据库中读取数据,然后回写到缓存中,然后才能从缓存中读取迁移之后的数据。

(3)一致性哈希分区

步骤:构造一致性哈希环、节点映射、路由规则。

1)构造一致性哈希环

通过哈希算法,将哈希值映射到哈希空间([0, 2^32])。

2)节点映射

将集群中的各节点映射到环上的某个一位置。比如集群中有三个节点,那么可以大致均匀的将其分布在环上。

3)路由规则

路由规则包括存储(setX)和取值(getX)规则。

当需要存储一个对时,首先计算键key的hash值:hash(key),这个hash值必然对应于一致性hash环上的某个位置,然后沿着这个值按顺时针找到第一个节点,并将该键值对存储在该节点上。

缺点:数据倾斜,不能对所有节点进行负载均衡

(4)虚拟槽分区

为了在增删节点的时候,各节点能够保持动态的均衡,将每个真实节点虚拟出若干个虚拟节点,再将这些虚拟节点随机映射到环上。此时每个真实节点不再映射到环上,真实节点只是用来存储键值对,它负责接应各自的一组环上虚拟节点。当对键值对进行存取路由时,首先路由到虚拟节点上,再由虚拟节点找到真实的节点。增加虚拟节点其实是减小了路由规则过程中的粒度,使每个真实节点可以分摊局部压力。

(5)Redis分区

槽位,共16384个槽位。

所有的键根据哈希函数映射到0 ~ 16383,计算公式:slot = CRC16(key)&16383

3. 主从复制

哨兵模式和集群模式,都需要进行主从复制。

核心流程:

建立连接,数据同步,命令传播

4. 分布式缓存的常见问题

4.1 缓存击穿

定义:缓存击穿是指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。

解决方案:

  1. 若缓存的数据是基本不会发生更新的,则可尝试设置热点数据永远不过期;
  2. 采用多级缓存架构,热点数据,肯定数据量不大,可以使用 本地缓存;
  3. 若缓存的数据更新频繁或者在缓存刷新的流程耗时较长的情况下,可以利用定时线程在缓存过期前主动地重新构建缓存或者延后缓存的过期时间,以保证所有的请求能一直访问到对应的缓存;
  4. 若缓存的数据更新不频繁,且缓存刷新的整个流程耗时较少的情况下可以加互斥锁,保障缓存中的数据,被第一次请求回填。此方案不适用于超高并发场景。

4.2 缓存穿透

定义:缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。

解决方案:

1、**接口校验。**在正常业务流程中可能会存在少量访问不存在 key 的情况,但是一般不会出现大量的情况,所以这种场景最大的可能性是遭受了非法攻击。可以在最外层先做一层校验:用户鉴权、数据合法性校验等,例如商品查询中,商品的ID是正整数,则可以直接对非正整数直接过滤等等。

2、缓存空值。当访问缓存和DB都没有查询到值时,可以将空值写进缓存,但是设置较短的过期时间,该时间需要根据产品业务特性来设置。

3、hashmap 记录存在性,存在去查redis,不存在直接返回。

4、布隆过滤器。使用布隆过滤器存储所有可能访问的 key,不存在的 key 直接被过滤,存在的 key 则再进一步查询缓存和数据库。

4.3 缓存雪崩

定义:缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。

解决方案:

  • 事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃;过期时间打散,热点数据不过期;
  • 事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
  • 事后:Redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。

4.4 缓存一致性

binlog,程序(mq)

4.4.1 cache pattern

No缓存不一致优点缺点适用场景
CacheAsideY实现比较简单需要维护两个数据存储,存在分布式事务问题延时要低,能容忍数据丢失和数据不一致
Read/Write ThroughN

使用简单

只需要关心缓存,数据写sh入数据库由框架完成,不需要处理分布式事务问题

延时高

同步操作,数据保证一致性
Write BehindY延时低数据丢失和数据不一致延时要低,能容忍数据丢失和数据不一致

4.4.2 CacheAside数据不一致问题

(1)出现原因

(2)解决方案

为什么是删除缓存?

很多时候,在复杂点的缓存场景,缓存不单单是数据库中直接取出来的值。

更新缓存的代价有时候是很高的。是不是说,每次修改数据库的时候,都一定要将其对应的缓存更新一份?也许有的场景是这样,但是对于比较复杂的缓存数据计算的场景,就不是这样了。如果你频繁修改一个缓存涉及的多个表,缓存也频繁更新。但是问题在于,这个缓存到底会不会被频繁访问到?

举个栗子,一个缓存涉及的表的字段,在 1 分钟内就修改了 20 次,或者是 100 次,那么缓存更新 20 次、100 次;但是这个缓存在 1 分钟内只被读取了 1 次,有大量的冷数据。实际上,如果你只是删除缓存的话,那么在 1 分钟内,这个缓存不过就重新计算一次而已,开销大幅度降低。用到缓存才去算缓存。
 

1)更新数据库 + 删除缓存

2)删除缓存 + 更新数据库

3)删除缓存 + 更新数据库 + sleep + 删除缓存

4)更新数据库 + 删除缓存消息入mq/binlog消息入mq + 监听消息删除缓存

5)分布式事务解决机制

4.5 数据丢失

1.AOF异步刷盘

2.master和slave的数据同步是异步的

5. 数据预热 & 冷热分离

6.多级缓存

6.1 二级缓存

6.1.1 本地缓存

(1)延时要求极高

因为本地缓存的访问速度最快

(2)hotKey问题

hotkey分布式缓存不能通过横向扩展来解决

(3)带宽限制

数据分摊到不同的缓存节点,但这成本比本地缓存高很多

6.1.2 多级缓存的数据一致性

不能使用删除策略,因为本地缓存一般是热点数据,删除会导致缓存击穿。

6.2 三级缓存

L3级缓存的数据一致性保障以及防止缓存击穿方案:

1.数据预热(或者叫预加载)

2.设置热点数据永远不过期,通过 ngx.shared.DICT的缓存的LRU机制去淘汰

3.如果缓存主动更新,在快过期之前更新,如有变化,通过订阅变化的机制,主动本地刷新

4.提供兜底方案,如果本地缓存没有,则通过后端服务获取数据,然后缓存起来

7. 缓存选型

由于 redis 只使用单核,而 memcached 可以使用多核,所以平均每一个核上 redis 在存储小数据时比memcached 性能更高。而在 100k 以上的数据中,memcached 性能要高于 redis。虽然 redis 最近也在存储大数据的性能上进行优化,但是比起 memcached,还是稍有逊色。

8. 缓存过期

8.1 过期策略

TTL, LFU, LRU, Random

8.2 过期删除策略

  • 定期删除:将每个设置了过期时间的 key 放入到一个独立的字典中,以后会定期遍历这个字典来删除到期的 key。
  • 惰性删除:所谓惰性策略就是在客户端访问这个key的时候,redis对key的过期时间进行检查,如果过期了就立即删除,不会给你返回任何东西。

定期删除是集中处理,惰性删除是零散处理。

9. BigKey问题

9.1 定义

Big Key就是某个key对应的value很大,占用的redis空间很大,本质上是大value问题。

9.2 产生原因

  • 1. redis数据结构使用不恰当
  • 2. 未及时清理垃圾数据
  • 3. 对业务预估不准确
  • 4. 热点数据列表

9.3 危害

1、阻塞请求、

2、内存增大

3、阻塞网络

4、影响主从同步、主从切换

9.4 bigKey识别

9.5 解决方案

1、对大Key进行拆分

2、对大Key进行清理

3、监控Redis的内存、网络带宽、超时等指标

4、定期清理失效数据

5、压缩value

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

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

相关文章

springboot177健身房管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

XGboost集成学习

XGBoost集成学习是一种基于决策树的集成方法&#xff0c;用于解决分类和回归问题。它是一种Gradient Boosting&#xff08;梯度提升&#xff09;的改进版&#xff0c;通过使用一系列弱学习器&#xff08;例如决策树&#xff09;的集合来构建一个更强大的模型。 XGBoost通过迭代…

DevOps:CI、CD、CB、CT、CD

目录 一、软件开发流程演化快速回顾 &#xff08;一&#xff09;瀑布模型 &#xff08;二&#xff09;原型模型 &#xff08;三&#xff09;螺旋模型 &#xff08;四&#xff09;增量模型 &#xff08;五&#xff09;敏捷开发 &#xff08;六&#xff09;DevOps 二、走…

python的os库常用代码

了解路径&#xff0c;就一定要先了解正斜杠 / 和反斜杠 \。在 MacOS 和 Linux 系统下&#xff0c;路径默认使用的都是正斜杠/&#xff0c;在Windows系统下&#xff0c;正反斜杠都可以表示路径分隔符&#xff0c;默认的是反斜杠 \。由于反斜杠本身属于转义符&#xff0c;如 \n 表…

Rust复合类型详解

在Rust中&#xff0c;复合类型是一种能够将多个值组合在一起的数据类型。本篇博客将介绍两种常见的复合类型&#xff1a;元组&#xff08;Tuple&#xff09;和数组&#xff08;Array&#xff09;。 Tuple&#xff08;元组&#xff09; 元组是Rust中的一种复合类型&#xff0c…

机器学习:过拟合和欠拟合的介绍与解决方法

过拟合和欠拟合的表现和解决方法。 其实除了欠拟合和过拟合&#xff0c;还有一种是适度拟合&#xff0c;适度拟合就是我们模型训练想要达到的状态&#xff0c;不过适度拟合这个词平时真的好少见。 过拟合 过拟合的表现 模型在训练集上的表现非常好&#xff0c;但是在测试集…

代码随想录刷题笔记 DAY 23 | 修剪二叉搜索树 No.669 | 将有序数组转换为二叉搜索树 No.108 | 把二叉搜索树转换为累加树 No.538

文章目录 Day 2301. 修剪二叉搜索树&#xff08;No. 669&#xff09;1.1 题目1.2 笔记1.3 代码 02. 将有序数组转换为二叉搜索树&#xff08;No. 108&#xff09;2.1 题目2.2 笔记2.3 代码 03. 把二叉搜索树转换为累加树&#xff08;No. 538&#xff09;3.1 题目3.2 笔记3.3 代…

Vue - 快速入门(一)

阅读文章可以收获&#xff1a; 1. 明白什么是vue 2. 如何创建一个vue实例 3. vue中的插值表达式如何使用 4. 如何安装vue的开发者工具 Vue 概念 什么是vue&#xff1f; Vue 是一个用于 构建用户界面 的 渐进式 框架 框架优点&#xff1a;大大提升开发效率 (70%↑) 缺点…

第80讲订单管理功能实现

后端 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace"com.java1234.mapper.OrderM…

深入学习Pandas:数据连接、合并、加入、添加、重构函数的全面指南【第72篇—python:数据连接】

深入学习Pandas&#xff1a;数据连接、合并、加入、添加、重构函数的全面指南 Pandas是Python中最强大且广泛使用的数据处理库之一&#xff0c;提供了丰富的函数和工具&#xff0c;以便更轻松地处理和分析数据。在本文中&#xff0c;我们将深入探讨Pandas中一系列数据连接、合…

python中的数组和list的异同

在Python中&#xff0c;数组和列表&#xff08;list&#xff09;是两个非常相似但又不完全一样的数据结构。实际上&#xff0c;Python本身并没有原生的数组类型&#xff0c;而列表&#xff08;list&#xff09;是Python提供的一种非常灵活且常用的序列类型。下面我将简要介绍它…

【教程】autojs使用Intent打开相机拍照并指定存储路径

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] var photoPath "/sdcard/a.jpg"; var photoFile new java.io.File(photoPath); if (!photoFile.exists()) {photoFile.getParentFile().mkdirs();} try {photoFile.createNewFile(); } catch (e) {to…

React18原理: 再聊Fiber架构下的时间分片

时间分片 react的任务可以被打断&#xff0c;其实就是基于时间分片的人眼最高能识别的帧数不超过30帧&#xff0c;电影的帧数差不多是在24浏览器的帧率一般来说是60帧&#xff0c;也就是每秒60个画面, 平均一个画面大概是16.5毫秒左右浏览器正常的工作流程是运算渲染&#xff…

【iOS操作系统——讲解】

iOS操作系统 iOS操作系统 iOS操作系统 iOS是苹果公司开发的移动操作系统&#xff0c;最初在2007年推出&#xff0c;当时伴随着第一代iPhone一起亮相&#xff0c;iOS是基于Darwin (BSD)操作系统核心的&#xff0c;并且具有对多点触控手势的原生支持&#xff0c;这些手势在iOS界…

UVA11181条件概率 Probability|Given

条件概率 Probability|Given - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 样例解释&#xff1a; 需要学习条件概率和贝叶斯定理 //1 2 - 0.1*0.2*(1-0.3) 0.014 //1 - 3 0.1*0.8*0.3 0.024 //- 2 3 0.9*0.2*0.3 0.054 // 0.092//(0.0140.024)/0.092 0.4…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之QRCode组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之QRCode组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、QRCode组件 用于显示单个二维码的组件。 子组件 无。 接口 QRCode(value: st…

python-分享篇-GUI界面开发-PyQt5-对QListWidget列表进行数据绑定

代码 # -*- coding: utf-8 -*-# Form implementation generated from reading ui file bindlist.ui # # Created by: PyQt5 UI code generator 5.11.3 # # WARNING! All changes made in this file will be lost! 对QListWidget列表进行数据绑定from PyQt5 import QtCore, QtG…

Elasticsearch:混合搜索是 GenAI 应用的未来

在这个竞争激烈的人工智能时代&#xff0c;自动化和数据为王。 从庞大的存储库中有效地自动化搜索和检索信息的过程的能力变得至关重要。 随着技术的进步&#xff0c;信息检索方法也在不断进步&#xff0c;从而导致了各种搜索机制的发展。 随着生成式人工智能模型成为吸引力的中…

华为云ModelBox实战:体感小游戏应用实操

目录 一、VsCode插件注册ModelBox设备二、Windows SDK安装1.安装Git for Windows2.下载ModelBox SDK3.相关插件安装 三、体感小游戏应用开发1.技能模板使用2.AI应用示例3.体感小游戏体验 参与华为云活动【HCSD】ModelBox实战营邀请活动&#xff0c;呼朋唤友学AIoT&#xff0c;完…

flask+python企业产品订单管理系统938re

在设计中采用“自下而上”的思想&#xff0c;在创新型产品提前购模块实现了个人中心、个体管理、发布企业管理、投资企业管理、项目分类管理、产品项目管理、个体投资管理、企业投资管理、个体订单管理、企业订单管理、系统管理等的功能性进行操作。最终&#xff0c;对基本系统…