当前位置: 首页 > news >正文

一次redis缓存不均衡优化经验

背景

高并发接口,引入redis作为缓存之后,运行一段时间发现redis各个节点在高峰时段的访问量严重不均衡,有的节点访问量7000次/s,有的节点访问量500次/s

此种现象虽然暂时不影响系统使用,但是始终是个安全隐患,随着业务量逐年上涨,风险留给未来,并非一个合格码农的职业操守。必须得看看究竟是何种情况。

思考

想要优化,得现有一番思考,先得想想究竟有哪些情况会产生这种现象,才能去逐步排查,而不能盲目就去动手。

可能的原因:

  1. 数据倾斜:如果某些键的访问频率较高,而这些键又恰好分布在某几个节点上,就会导致节点的访问不均衡。这可能是因为数据分布不均匀,或者业务逻辑导致某些键的访问频率较高。
  2. 网络问题:网络延迟或带宽限制可能导致某些节点的访问速度较慢,从而使访问不均衡。
  3. 客户端连接问题:如果某些客户端连接到了某个特定节点,而其他节点上的客户端较少,就会导致节点的访问不均衡.
  4. 业务逻辑问题:是否是因为业务逻辑原因导致的频繁访问同一批数据
  5. 是否存在热key

验证

有了上述思考,就要开始去逐一排查可能的原因

1.数据倾斜排查:检查数据在节点之间的分布情况,通过查看Redis的CPU、内存指标,并未发现某个节点的负载明显高于其他节点

2.网络问题:通过监测网络延迟或带宽限制相关情况,并未发现有此种情况

3.客户端连接问题:检查客户端连接到Redis节点的方式,如果发现某些节点受到过多的请求压力,可以考虑采用负载均衡策略,将请求均匀分散到不同的节点上;通过相关检查,并未发现此类问题

4.业务逻辑问题:分析Redis访问相关业务代码及定时任务,并未发现有重复访问的逻辑存在

5.是否存在热key:通过运维获取高峰时段的访问日志,进行统计分析,

(1) 热key有两类:网点映射+以业务账号维度的数据

(2)redis访问不均衡的原因:不同客户下单高峰分布在一天不同时间段,高频访问在不同时间分布在不同节点上

方案

通过三种策略来确保redis各节点的访问均衡

1.本地缓存策略

将将要缓存的数据根据业务形态分为两类:

(1)网点类的常用数据直接缓存在本地

(2)对于高峰时期高频访问的数据,引入缓存组件Caffeine,设置相关的策略

设置大小为1M

EXPIRE_AFTER_WRITE_TIME(60s)

EXPIRE_AFTER_ACCESS_TIME(10s)

2.节点一致性策略

使用发布-订阅模式(Pub-Sub)来实现更新通知机制; 当 Redis 中的数据更新时,Redis 可以发布一个更新通知,各节点的本地缓存订阅这个通知,并根据通知更新本地缓存

3.异常解决方案

(1)异常日志记录

(2)间隔2min重试机制

(3)重试后异常告警机制

(4)数据定时同步(兜底): DB->redis、redis->本地缓存

下图为存储与访问缓存的逻辑图:

 效果

经过上述方案的实施,最终实现了:

1.redis各节点的访问量在全时段实现了均衡态

2.redis的各节点的整体QPS也下降了10%

3.像双十一双十二高峰时段接口也是稳稳的

本地缓存原理及方案选取原因

本地缓存是指将数据存储在应用程序的本地内存中,以提高数据的读取速度和访问效率。本地缓存的本质是通过将常用或热点数据保存在内存中,避免了每次访问都需要从远程或磁盘存储中读取数据的开销。

本地缓存的工作原理如下:
1.数据加载:当应用程序第一次访问某个数据时,如果该数据还未被缓存,则从远程或磁盘存储中加载数据,并将其保存在本地缓存中。
2.数据访问:当应用程序再次访问同样的数据时,首先从本地缓存中查找数据。如果数据存在于缓存中,则直接返回缓存的数据,避免了从远程或磁盘存储中读取的开销。
3.缓存更新:当数据发生变化时,需要更新缓存中的数据,以保持缓存和存储中的数据一致性。可以通过手动或自动的方式更新缓存,例如定时刷新缓存、监听数据变更事件等。
本地缓存的优势包括快速访问、低延迟、减轻了远程或磁盘存储的负载等。它适用于那些访问频率较高、数据相对稳定的场景,可以大大提高应用程序的性能和响应速度。

但是需要注意的是,本地缓存也存在一些问题,如缓存过期、缓存一致性、内存管理等。开发者需要根据具体的应用场景和需求,合理配置和管理本地缓存,以充分发挥其优势同时避免潜在的问题。

传统缓存组件方案:

FIFO:按照数据最早进入缓存的顺序进行替换。即,先进入缓存的数据先被替换掉。FIFO策略简单直观,但可能导致缓存命中率较低,因为最早进入缓存的数据可能不一定是最常用的数据。

LRU:根据数据最近被访问的时间进行替换。即,最长时间未被访问的数据会被替换掉。LRU策略基于“时间局部性”原理,认为最近被访问的数据更有可能在将来被访问,因此替换最久未被访问的数据。但实现LRU策略需要维护访问数据的顺序,可能带来一定的开销。

LFU:根据数据被访问的频率进行替换。即,最不经常被访问的数据会被替换掉。LFU策略基于“访问局部性”原理,认为最常被访问的数据更有可能在将来继续被访问,因此替换最不经常被访问的数据。但实现LFU策略需要维护数据的访问频率,可能带来更大的开销。

Caffeine
一个高性能、高命中率、接近最优的本地缓存,被称为”新一代缓存“或”现代缓存之王。

脱胎于Guava Cache , 结合LRU+LFU的优势,使用一种W-TinyLFU的算法结构

从Spring5开始,Caffeine将取代Guava Cache成为Spring默认的缓存组件

Caffeine是一个基于Java的内存缓存库,与其他缓存组件相比,它具有以下几个优势:

  1. 高性能:Caffeine被设计成高性能的缓存库,它使用了多种优化技术来提供快速的缓存访问,包括使用本地内存和原生数据结构,避免了不必要的开销。
  2. 低延迟:Caffeine的设计目标之一是提供低延迟的缓存访问。它采用了基于时间戳的缓存失效策略和预先加载机制,以减少对外部资源的依赖和等待时间。
  3. 强大的功能:Caffeine提供了丰富的功能,包括缓存过期、缓存加载、缓存刷新、缓存移除等。它支持异步加载和自定义缓存策略,可以根据具体需求进行灵活配置。
  4. 内存管理:Caffeine提供了细粒度的内存管理功能,可以设置缓存的最大大小、最大条目数、过期时间等。它还支持缓存的自动回收和大小基于权重的淘汰策略,可以有效地管理内存。
  5. 易于使用:Caffeine提供了简单易用的API,可以方便地创建和管理缓存。它还提供了详细的文档和示例代码,以帮助开发者快速上手和集成。

Caffeine在性能、延迟、功能和内存管理等方面都具有优势,适用于对缓存性能要求较高的场景。它可以作为Java应用程序的缓存解决方案,提供快速、可靠和灵活的缓存支持。

 

相关文章:

一次redis缓存不均衡优化经验

背景 高并发接口,引入redis作为缓存之后,运行一段时间发现redis各个节点在高峰时段的访问量严重不均衡,有的节点访问量7000次/s,有的节点访问量500次/s 此种现象虽然暂时不影响系统使用,但是始终是个安全隐患&#x…...

npm发布包

1.npm 登录 在控制台输入命令 npm login 按提示输入用户名,密码,邮箱后登录 如果出现如下提示 需要将淘宝镜像源切换为npm源,删除或注释以下内容就行 2.发布 进入准备发布的代码的根目录下,输入命令 npm publish 3.删除已发…...

Qt5.13引入QtWebApp的模块后报错: error C2440: “reinterpret_cast”: 无法从“int”转换为“quintptr”

1、开发环境 Win10-64 qt5.13 msvc2015-64bit-release 2、报错 新建一个demo工程。 引入QtWebApp的httpserver、logging、templateengine三个模块后。 直接运行,,此时报错如下: E:\Qt5.13.1\install\5.13.1\msvc2015_64\include\QtCore…...

软件为什么要进行性能压力测试?

软件为什么要进行性能压力测试?随着软件应用的不断增多和复杂度的提高,软件的性能对用户体验和业务成功至关重要。性能问题可能导致软件运行缓慢、崩溃或无响应,给用户带来不便甚至损失。为了确保软件能够在高负载和压力下正常运行&#xff0…...

阻塞队列BlockingQueue详解

一、阻塞队列介绍 1、队列 队列入队从队首开始添加,直至队尾;出队从队首出队,直至队尾,所以入队和出队的顺序是一样的 Queue接口 add(E) :在指定队列容量条件下添加元素,若成功返回true,若当前…...

pygame贪吃蛇游戏

pygame贪吃蛇游戏 贪吃蛇游戏通过enter键启动,贪吃蛇通过WSAD进行上下左右移动,每次在游戏区域中随机生成一个食物,每次吃完食物后,蛇变长并且获得积分;按空格键暂停。 贪吃蛇 import random, sys, time, pygame from …...

Mac系统下使用远程桌面连接Windows系统

一、远程桌面工具 Microsoft Remote Desktop 二、下载地址 https://go.microsoft.com/fwlink/?linkid868963 三、下载并安装 四、添加远程PC PC name:云服务器IP。 User account: 添加系统用户 PC name:远程桌面 IP 地址User account:可以选择是…...

使用 OpenCV 和深度学习对黑白图像进行着色

在本文中,我们将创建一个程序将黑白图像(即灰度图像)转换为彩色图像。我们将为此程序使用 Caffe 着色模型。您应该熟悉基本的 OpenCV 功能和用法,例如读取图像或如何使用 dnn 模块加载预训练模型等。现在让我们讨论实现该程序所遵循的过程。 给定一张灰度照片作为输入,本文…...

从价值的角度看,为何 POSE 通证值得长期看好

PoseSwap 是 Nautilus Chain 上的首个 DEX,基于 Nautilus Chain 也让其成为了首个以模块化构建的 Layer3 架构的 DEX。该 DEX 本身能够以 Dapp 层(Rollup)的形态,与其他应用层并行化运行。...

pytorch的CrossEntropyLoss交叉熵损失函数默认reduction是平均值

pytorch中使用nn.CrossEntropyLoss()创建出来的交叉熵损失函数计算损失默认是求平均值的,即多个样本输入后获取的是一个均值标量,而不是样本大小的向量。 net nn.Linear(4, 2) loss nn.CrossEntropyLoss() X torch.rand(10, 4) y torch.ones(10, dt…...

OKR管理策略:为开发团队注入动力

引言 在这个快速变化的世界中,公司需要迅速应对市场变化,并保持其目标和战略的清晰性和一致性。而OKR(Objectives and Key Results)正是这个挑战的解决方案之一。OKR的实施可以帮助开发团队明确目标,关注关键结果&…...

C++二叉搜索树剖析

目录 🍇二叉搜索树概念🍈二叉搜索树查找🍉二叉搜索树的插入🍊二叉搜索树的删除🍍二叉搜索树的查找、插入、删除实现🍋二叉搜索树的应用🥭二叉搜索树的性能分析🍓总结 🍇二…...

升级你的GitHub终端认证方式:从密码到令牌

升级你的GitHub终端认证方式:从密码到令牌 前言 GitHub官方在2021年8月14日进行了一次重大改变,它将终端推送代码时所需的身份认证方式从密码验证升级为使用个人访问令牌(Personal Access Token)。这个改变引起了一些新的挑战&am…...

【力扣】链表题目总结

文章目录 链表基础题型一、单链表翻转、反转、旋转1.反转链表2.反转链表II——反转部分链表3.旋转链表4.K个一组翻转链表5.反转偶数长度组的节点 二、删除单链表中的结点1.删除链表的结点2.删除未排序链表中的重复节点3.删除已排序链表中的重复元素I——重复元素只剩下一个4.删…...

Thunar配置自定义动作

Add “Copy To” and “Move To” custom actions in Thunar file manager | For the record 1.在此打开终端 图标-应用程序:utilities-terminal 命令:exo-open --working-directory %f --launch TerminalEmulator 文件类型:* 目录 2.右键增…...

Python 开发工具 Pycharm —— 使用技巧Lv.3

单步执行调试 1: 鼠标左键单击红点是断点行 2:甲虫样式是进行调试方式运行,鼠标左键单击点击 3: 单步运行图标,点击让程序运行一行 4: 步入步出,可以进入当前代码行函数内 5:重新运行…...

51单片机(普中HC6800-EM3 V3.0)实验例程软件分析 实验三 LED流水灯

目录 前言 一、原理图及知识点介绍 二、代码分析 知识点五:#include 中的库函数解析 _crol_,_irol_,_lrol_ _cror_,_iror_,_lror_ _nop_ _testbit_ 前言 第一个实验:51单片机(普中HC6800-EM3 V3.0…...

深度学习与计算机相结合:直播实时美颜SDK的创新之路

时下,实时美颜技术就成为了直播主们的得力工具,它可以在直播过程中即时处理视频画面。而支持实时美颜功能的SDK更是推动了这项技术的发展,让直播主和普通用户都能轻松使用美颜功能。 一、美颜技术的演进 早期的美颜技术主要依赖于简单的图…...

Unity寻找子物体的方法

1.GetComponentsInChildren() 查找单个子物体 GameObject childObjectGetComponentInChildren<Transform>(); 查找多个子物体 Transform[] myTransforms GetComponentsInChildren<Transform>(); foreach (var child in myTransforms){ Debug.Log(child.name…...

车载软件架构 —— 车载软件安全启动关键技术解读

车载软件架构 —— 车载软件安全启动关键技术解读 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...

uniapp获取当前位置和经纬度信息

1.1. 获取当前位置和经纬度信息&#xff08;需要配置高的SDK&#xff09; 调用uni-app官方API中的uni.chooseLocation()&#xff0c;即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...

【R语言编程——数据调用】

这里写自定义目录标题 可用库及数据集外部数据导入方法查看数据集信息 在R语言中&#xff0c;有多个库支持调用内置数据集或外部数据&#xff0c;包括studentdata等教学或示例数据集。以下是常见的库和方法&#xff1a; 可用库及数据集 openintro库 该库包含多个教学数据集&a…...