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

缓存与数据库数据一致性:旁路缓存、读写穿透和异步写入模式解析

旁路缓存模式、读写穿透模式和异步缓存写入模式是三种常见的缓存使用模式,以下是对三种经典缓存使用模式在缓存与数据库数据一致性方面更全面的分析:

一、旁路缓存模式(Cache - Aside Pattern)

1.数据读取流程

  • 应用程序首先向缓存发送读取请求,检查所需数据是否在缓存中。
  • 如果缓存命中,直接从缓存中获取数据并返回给应用程序,这能极大提高读取速度,减少数据库的负载。
  • 若缓存未命中,应用程序接着向数据库发送读取请求,从数据库获取数据。获取到数据后,一方面将数据返回给应用程序,另一方面把数据写入缓存,同时可以设置缓存数据的过期时间,以便在数据更新后能及时从数据库重新获取最新数据。

2.数据写入流程

  • 当应用程序要更新数据时,首先更新数据库中的数据,确保数据库作为数据的可靠来源得到及时更新。
  • 在数据库更新成功后,立即删除缓存中对应的旧数据。这样做是为了让下次读取该数据时,能从数据库获取到最新数据并更新到缓存中,保证缓存数据的时效性。

3.一致性分析

  • 优点
    • 实现相对简单,在正常情况下能较好地保证数据一致性。以数据库为数据的权威来源,缓存主要用于加速读取,通过先更新数据库再删除缓存的操作顺序,多数情况下能确保缓存数据要么是最新的,要么不存在,等待下次读取时更新。
    • 读性能优化明显,缓存命中时能快速响应读取请求,减轻数据库压力,适用于读多写少的场景。
  • 缺点
    • 在高并发场景下可能出现数据不一致问题。例如,两个并发更新操作同时对同一数据进行修改,若操作 A 先更新数据库但在删除缓存前,操作 B 更新数据库并先于操作 A 删除缓存,接着操作 A 再删除缓存,此时缓存中无最新数据,读取请求可能获取到旧数据,直到下次缓存更新。
    • 缓存数据的过期时间设置较为关键,若设置过长,可能导致缓存数据长时间不一致;设置过短,则会增加数据库的读取压力。

4.代码实例

import redis.clients.jedis.Jedis;
import java.sql.*;public class CacheAsidePattern {private static final String REDIS_HOST = "localhost";private static final int REDIS_PORT = 6379;private static final String DB_URL = "jdbc:mysql://localhost:3306/testdb";private static final String DB_USER = "root";private static final String DB_PASSWORD = "password";public static void main(String[] args) {try (Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {// 创建表createTable(conn);// 插入示例数据insertSampleData(conn);// 测试读取String userName = getUser(jedis, conn, 1);System.out.println("用户姓名: " + userName);// 测试更新updateUser(jedis, conn, 1, "Bob");userName = getUser(jedis, conn, 1);System.out.println("更新后用户姓名: " + userName);} catch (SQLException e) {e.printStackTrace();}}private static void createTable(Connection conn) throws SQLException {String createTableSQL = "CREATE TABLE IF NOT EXISTS users (" +"id INT PRIMARY KEY, " +"name VARCHAR(255))";try (Statement stmt = conn.createStatement()) {stmt.executeUpdate(createTableSQL);}}private static void insertSampleData(Connection conn) throws SQLException {String insertSQL = "INSERT IGNORE INTO users (id, name) VALUES (1, 'Alice')";try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {pstmt.executeUpdate();}}private static String getUser(Jedis jedis, Connection conn, int userId) {String key = "user:" + userId;String user = jedis.get(key);if (user != null) {System.out.println("从缓存中获取数据");return user;} else {try (PreparedStatement pstmt = conn.prepareStatement("SELECT name FROM users WHERE id = ?")) {pstmt.setInt(1, userId);ResultSet rs = pstmt.executeQuery();if (rs.next()) {user = rs.getString("name");jedis.set(key, user);System.out.println("从数据库中获取数据并写入缓存");return user;}} catch (SQLException e) {e.printStackTrace();}return null;}}private static void updateUser(Jedis jedis, Connection conn, int userId, String newName) {String key = "user:" + userId;try (PreparedStatement pstmt = conn.prepareStatement("UPDATE users SET name = ? WHERE id = ?")) {pstmt.setString(1, newName);pstmt.setInt(2, userId);pstmt.executeUpdate();jedis.del(key);System.out.println("数据库更新并删除缓存");} catch (SQLException e) {e.printStackTrace();}}
}    

二、读写穿透模式(Write - Through Pattern)

1.数据读取流程

  • 应用程序向缓存发送读取请求,尝试从缓存中获取数据。
  • 如果缓存命中,直接从缓存中返回数据给应用程序。
  • 若缓存未命中,应用程序从数据库读取数据,读取到数据后,将数据返回给应用程序,同时将数据写入缓存,且写入缓存操作是同步进行的,确保数据在缓存和数据库中同时更新。

2.数据写入流程

  • 当应用程序执行写操作时,会同时向缓存和数据库发送更新请求。先将数据写入缓存,然后由缓存负责将数据同步到数据库,通常通过缓存的写入操作触发对数据库的写入,保证缓存和数据库数据的实时同步。

3.一致性分析

  • 优点
    • 能严格保证数据一致性,每次读写操作都确保缓存和数据库的数据同步更新,两者就像一个整体,任何一方的更新立即反映到另一方,不存在数据延迟或不一致的情况。
    • 对于读写操作较为均衡的场景,该模式能较好地适应,不会出现因写操作频繁导致缓存与数据库数据不一致的问题。
  • 缺点
    • 由于缓存和数据库是不同存储系统,其写入性能和可靠性存在差异,可能出现缓存写入成功但数据库写入失败的情况,导致数据不一致。
    • 为保证一致性引入的补偿机制,如重试机制或事务机制,会增加系统复杂性和开发成本。同时,同步写入操作可能会降低写操作的性能,因为需要等待数据库写入完成才能返回结果。

4.代码实例

import redis.clients.jedis.Jedis;
import java.sql.*;public class WriteThroughPattern {private static final String REDIS_HOST = "localhost";private static final int REDIS_PORT = 6379;private static final String DB_URL = "jdbc:mysql://localhost:3306/testdb";private static final String DB_USER = "root";private static final String DB_PASSWORD = "password";public static void main(String[] args) {try (Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {// 创建表createTable(conn);// 插入示例数据insertSampleData(conn);// 测试读取String userName = getUser(jedis, conn, 1);System.out.println("用户姓名: " + userName);// 测试更新updateUser(jedis, conn, 1, "Bob");userName = getUser(jedis, conn, 1);System.out.println("更新后用户姓名: " + userName);} catch (SQLException e) {e.printStackTrace();}}private static void createTable(Connection conn) throws SQLException {String createTableSQL = "CREATE TABLE IF NOT EXISTS users (" +"id INT PRIMARY KEY, " +"name VARCHAR(255))";try (Statement stmt = conn.createStatement()) {stmt.executeUpdate(createTableSQL);}}private static void insertSampleData(Connection conn) throws SQLException {String insertSQL = "INSERT IGNORE INTO users (id, name) VALUES (1, 'Alice')";try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {pstmt.executeUpdate();}}private static String getUser(Jedis jedis, Connection conn, int userId) {String key = "user:" + userId;String user = jedis.get(key);if (user != null) {System.out.println("从缓存中获取数据");return user;} else {try (PreparedStatement pstmt = conn.prepareStatement("SELECT name FROM users WHERE id = ?")) {pstmt.setInt(1, userId);ResultSet rs = pstmt.executeQuery();if (rs.next()) {user = rs.getString("name");jedis.set(key, user);System.out.println("从数据库中获取数据并写入缓存");return user;}} catch (SQLException e) {e.printStackTrace();}return null;}}private static void updateUser(Jedis jedis, Connection conn, int userId, String newName) {String key = "user:" + userId;try {conn.setAutoCommit(false);jedis.set(key, newName);try (PreparedStatement pstmt = conn.prepareStatement("UPDATE users SET name = ? WHERE id = ?")) {pstmt.setString(1, newName);pstmt.setInt(2, userId);pstmt.executeUpdate();}conn.commit();System.out.println("缓存和数据库同时更新");} catch (SQLException e) {try {conn.rollback();} catch (SQLException rollbackEx) {rollbackEx.printStackTrace();}System.out.println("更新失败: " + e.getMessage());}}
}    

三、异步缓存写入模式(Write - Behind Caching Pattern)

1.数据读取流程

  • 与前两种模式类似,应用程序首先从缓存中读取数据。
  • 若缓存命中,直接返回数据。
  • 缓存未命中时,从数据库读取数据并返回给应用程序,同时将数据写入缓存。

2.数据写入流程

  • 写操作发生时,应用程序只将数据写入缓存,然后由缓存负责在后台异步地将数据批量写入数据库。可以根据一定的策略,如达到一定的写入次数或经过一定的时间间隔,将缓存中的数据批量刷写到数据库。

3.一致性分析

  • 优点
    • 写性能极高,应用程序无需等待数据库写入完成即可快速响应写请求,能显著提高系统吞吐量,适用于写操作频繁的场景,如日志记录、实时数据采集等。
    • 通过批量写入数据库,减少了数据库的写入次数,降低了数据库的 I/O 压力,有助于提高数据库的性能和稳定性。
  • 缺点
    • 数据一致性问题较为严重。由于数据是异步写入数据库的,在写入缓存后到写入数据库之前的时间段内,若发生系统故障、缓存数据丢失或缓存服务崩溃等情况,可能导致数据丢失,破坏数据一致性。
    • 为保证数据一致性采取的措施,如持久化缓存、合理设置缓存刷写策略、系统恢复时的数据恢复操作等,增加了系统的复杂性和运维成本。同时,还需考虑数据库写入的并发控制,避免数据冲突和不一致。

4.代码实例

import redis.clients.jedis.Jedis;
import java.sql.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class WriteBehindCachingPattern {private static final String REDIS_HOST = "localhost";private static final int REDIS_PORT = 6379;private static final String DB_URL = "jdbc:mysql://localhost:3306/testdb";private static final String DB_USER = "root";private static final String DB_PASSWORD = "password";private static final int FLUSH_INTERVAL = 5; // 每 5 秒刷写一次public static void main(String[] args) {try (Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {// 创建表createTable(conn);// 插入示例数据insertSampleData(conn);// 启动异步刷写任务ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);executor.scheduleAtFixedRate(() -> flushCacheToDB(jedis, conn), 0, FLUSH_INTERVAL, TimeUnit.SECONDS);// 测试读取String userName = getUser(jedis, conn, 1);System.out.println("用户姓名: " + userName);// 测试更新updateUser(jedis, conn, 1, "Bob");userName = getUser(jedis, conn, 1);System.out.println("更新后用户姓名: " + userName);// 关闭线程池executor.shutdown();} catch (SQLException e) {e.printStackTrace();}}private static void createTable(Connection conn) throws SQLException {String createTableSQL = "CREATE TABLE IF NOT EXISTS users (" +"id INT PRIMARY KEY, " +"name VARCHAR(255))";try (Statement stmt = conn.createStatement()) {stmt.executeUpdate(createTableSQL);}}private static void insertSampleData(Connection conn) throws SQLException {String insertSQL = "INSERT IGNORE INTO users (id, name) VALUES (1, 'Alice')";try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {pstmt.executeUpdate();}}private static String getUser(Jedis jedis, Connection conn, int userId) {String key = "user:" + userId;String user = jedis.get(key);if (user != null) {System.out.println("从缓存中获取数据");return user;} else {try (PreparedStatement pstmt = conn.prepareStatement("SELECT name FROM users WHERE id = ?")) {pstmt.setInt(1, userId);ResultSet rs = pstmt.executeQuery();if (rs.next()) {user = rs.getString("name");jedis.set(key, user);System.out.println("从数据库中获取数据并写入缓存");return user;}} catch (SQLException e) {e.printStackTrace();}return null;}}private static void updateUser(Jedis jedis, Connection conn, int userId, String newName) {String key = "user:" + userId;jedis.set(key, newName);System.out.println("数据写入缓存,等待异步刷写数据库");}private static void flushCacheToDB(Jedis jedis, Connection conn) {try {conn.setAutoCommit(false);// 模拟获取所有用户缓存数据// 实际应用中需要根据业务逻辑获取待刷写的数据String keyPattern = "user:*";for (String key : jedis.keys(keyPattern)) {int userId = Integer.parseInt(key.split(":")[1]);String userName = jedis.get(key);try (PreparedStatement pstmt = conn.prepareStatement("UPDATE users SET name = ? WHERE id = ?")) {pstmt.setString(1, userName);pstmt.setInt(2, userId);pstmt.executeUpdate();}}conn.commit();System.out.println("缓存数据刷写到数据库");} catch (SQLException e) {try {conn.rollback();} catch (SQLException rollbackEx) {rollbackEx.printStackTrace();}System.out.println("刷写失败: " + e.getMessage());}}
}    

三种经典缓存使用模式在缓存与数据库数据一致性方面各有优劣。在实际应用中,需要根据业务对数据一致性的严格程度、读写操作的频率和性能要求等因素,综合权衡选择合适的缓存模式,并通过相应的技术手段和策略来最大程度地保障数据一致性。

相关文章:

缓存与数据库数据一致性:旁路缓存、读写穿透和异步写入模式解析

旁路缓存模式、读写穿透模式和异步缓存写入模式是三种常见的缓存使用模式,以下是对三种经典缓存使用模式在缓存与数据库数据一致性方面更全面的分析: 一、旁路缓存模式(Cache - Aside Pattern) 1.数据读取流程 应用程序首先向缓…...

HTML邮件背景图兼容 Outlook

在 HTML 邮件中设置背景图片时,Outlook(尤其是桌面版的 Outlook for Windows)经常不会正确显示背景图,这是因为outlook 是使用 Word 作为邮件渲染引擎,而不是标准的 HTML/CSS 渲染方式。 推荐的解决方案:使…...

Linux之七大难命令(The Seven Difficult Commands of Linux)

Linux之七大难命令 、背景 作为Linux的初学者,肯定要先掌握高频使用的指令,这样才能让Linux的学习在短时间内事半功倍。但是,有些指令虽然功能强大,但因参数多而让初学者们很害怕,今天介绍Linux中高频使用&#xff0…...

每日Html 4.24

&#x1f4da; 每日一个Html小知识 &#x1f40d; 每天花1分钟&#xff0c;解锁一个Html实用技巧/冷知识&#xff01;无论是新手还是老手&#xff0c;这里都有让你眼前一亮的编程干货。 ✨ 今日主题&#xff1a;<dialog> 标签 &#x1f4a1; 你知道吗&#xff1f; 浏览…...

YOLOv11改进-双Backbone架构:利用双backbone提高yolo11目标检测的精度

一、引言&#xff1a;为什么我们需要双Backbone&#xff1f; 在目标检测任务中&#xff0c;YOLO系列模型因其高效的端到端检测能力而备受青睐。然而&#xff0c;传统YOLO模型大多采用单一Backbone结构&#xff0c;即利用一个卷积神经网络&#xff08;CNN&#xff09;作为特征提…...

嵌入式Linux驱动开发:LED实验

在嵌入式Linux驱动开发中&#xff0c;LED实验可以通过多种方式实现&#xff0c;主要包括设备树下的LED实验、新字符设备驱动的LED实验和GPIO子系统的LED实验。这三种方式在硬件资源管理、驱动架构和开发流程上有显著区别&#xff0c;下面从多个维度进行对比分析&#xff1a; 1.…...

系统与网络安全------弹性交换网络(2)

资料整理于网络资料、书本资料、AI&#xff0c;仅供个人学习参考。 Eth-Trunk 组网中经常会遇到的问题 链路聚合技术 概述 Eth-Trunk&#xff08;链路聚合技术&#xff09;作为一种捆绑技术&#xff0c;可以把多个独立的物理接口绑定在一起&#xff0c;作为一个大带宽的逻辑…...

Kotlin Multiplatform--01:项目结构基础

Kotlin Multiplatform--01&#xff1a;项目结构基础 引言Common CodeTargetsExpected 和 actual1.使用函数2.使用接口 引言 以下为使用 Android Studio 创建的默认 Kotlin Multiplatform 的项目结构&#xff0c;本章将对项目结构进行简单介绍&#xff0c;让读者对 Kotlin Multi…...

SEO(Search Engine Optimization,搜索引擎优化)相关知识点

SEO&#xff08;Search Engine Optimization&#xff09;是指搜索引擎优化&#xff0c;是计算机领域中通过技术手段和内容策略&#xff0c;提升网站在搜索引擎&#xff08;如Google、Bing、百度&#xff09;中自然&#xff08;非付费&#xff09;排名的系统性方法。是一种通过优…...

轻松完成视频创作,在线视频编辑器,无需下载软件,功能多样实用!

小白工具的在线视频编辑https://www.xiaobaitool.net/videos/edit/ 功能丰富、操作简便&#xff0c;在线裁剪或编辑视频工具&#xff0c;轻松完成视频创作能满足多种视频编辑需求。 格式支持广泛&#xff1a;可编辑超百种视频格式&#xff0c;基本涵盖常见和小众视频格式&#…...

typescript学习笔记(全)

1.安装 全局安装 npm i -g typescript局部安装 npm i typescript初始化 tsc --init就会在所在目录下创建出一个tsconfig.json的ts配置文件 2.编译 如果是全局安装 tsc index.ts就会在同目录下编译出一个index.js文件 如果是局部安装 npx tsc index.ts3.特性 1.静态类…...

centos挂载新的硬盘

如果要将 nvme0n1 挂载到 /data 目录&#xff08;而不是 /&#xff09;&#xff0c;操作会更简单&#xff0c;无需迁移系统文件。以下是详细步骤&#xff1a; 1. 检查磁盘情况 lsblk输出&#xff1a; NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 …...

​​客户案例 | 西昊智能家具:日事清【目标】【日程】【项目】助力高效OKR管理

随着社会现代化、科技化的发展&#xff0c;人们越来越青睐智能化的家具产品&#xff0c;以此来提升家居的安全性、便利性与舒适性。目前&#xff0c;智能家具的行业规模正在不断扩张&#xff0c;产业也逐渐步入高质量增长模式。面对繁荣的市场前景&#xff0c;西昊智能家具与日…...

16.磁环在EMC设计中的选型与运用

磁环在EMC设计中的选型与运用 1. 磁环选型的参数和注意事项2. 磁环的选型方法3. 非晶磁环 1. 磁环选型的参数和注意事项 &#xff08;1&#xff09;损耗电阻R(f)和L(f)是频率的函数&#xff0c;因此IL也是频率的函数&#xff1b; &#xff08;2&#xff09;fL段&#xff0c;R(f…...

oralce 查询未提交事务和终止提交事务

查询提交记录 SELECT s.sid,s.serial#,s.username,s.status,t.start_time,t.used_ublk,t.log_io,t.phy_io FROM v$session sJOIN v$transaction t ON s.saddr t.ses_addr; 查到的记录如下&#xff1a; 如果要终止第一次提交&#xff0c;如下操作 ALTER SYSTEM KILL SESSION…...

智能小助手部署 Win10 + ollama的Deepseek + CentOS+ maxKB

一、适用场景 1、企业内部知识管理 &#xff08;1&#xff09;快速查询政策与流程文档&#xff1a; 员工通过自然语言提问&#xff0c;MaxKB 能迅速定位相关文档并给出准确答案&#xff0c;减少人工检索成本&#xff0c;提升企业内部知识获取的效率。 &#xff08;2&#xff0…...

CentOS 7 系统中,防火墙要怎么使用?

在 CentOS 7 系统中&#xff0c;默认有两个防火墙管理工具&#xff1a; firewalld&#xff08;默认的动态防火墙&#xff0c;基于 D-Bus 管理&#xff09; iptables&#xff08;传统的静态防火墙&#xff0c;底层由 netfilter 提供支持&#xff09; 是否需要关闭这两个防火墙…...

网页版 deepseek 对话问答内容导出为 PDF 文件和 Word 文件的浏览器插件下载安装和使用说明

文章目录 网页版 deepseek 浏览器扩展应用程序插件1. 预览效果2. 功能介绍3. 浏览器扩展应用程序下载3.1. 下载方式13.2. 下载方式24. 安装教程4.1. Chrome 浏览器安装步骤4.2. Edge 浏览器安装步骤5. 使用说明网页版 deepseek 浏览器扩展应用程序插件 1. 预览效果 预览效果 导…...

MySQL 报错解析:SQLSyntaxErrorException caused by extra comma before FROM

一、遇到的错误 在日常开发中&#xff0c;尤其是使用 MyBatis 等 ORM 框架操作 SQL 时&#xff0c;我们经常会遇到类似下面的错误。 ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that co…...

高光谱相机在生物医学中的应用:病理分析、智慧中医与成分分析

高光谱成像技术&#xff08;Hyperspectral Imaging, HSI&#xff09;通过捕捉物质的连续光谱信息与空间信息&#xff0c;形成“光谱立方体”&#xff0c;能够揭示传统成像技术无法获取的分子级特征。作为国内光谱技术领域的领军企业&#xff0c;深圳市中达瑞和科技有限公司依托…...

2025 年“泰迪杯”数据挖掘挑战赛B题——基于穿戴装备的身体活动监测问题分析

摘要 本文聚焦于基于穿戴设备采集的加速度计数据,深入研究志愿者在日常活动中的行为特征,构建了多个数学建模框架,实现从身体活动监测、能耗预测、睡眠阶段识别到久坐预警等多个目标。我们依托于多源数据融合与机器学习模型,对人体活动状态进行识别与分析,为健康管理、行…...

10.接口而非实现编程

10.接口而非实现编程 目录介绍 01.接口编程原则 1.1 接口指导思想 02.如何理解接口 2.1 重点搞清楚接口2.2 抽象的思想 03.来看一个案例 3.1 图片存储的案例3.2 业务拓展问题3.3 代码演变设计思想3.4 重构后的代码 04.定义接口的场景 4.1 要有接口意识4.2 接口具体的场景4.3 …...

基于大语言模型的AI智能体开发:构建具备工具使用能力的智能助手

本文将结合大语言模型&#xff08;LLM&#xff09;与工具调用能力&#xff0c;构建新一代AI智能体系统。通过ReAct框架实现智能思考-行动循环&#xff0c;集成网络搜索、计算器、API调用等外部工具&#xff0c;并基于LangChain实现可扩展的智能体架构。 一、新一代AI智能体技术…...

DS B/B+/B*树及其应用(21)

文章目录 前言一、常见的搜索结构内查找外查找 二、B树的概念三、B树的插入分析四、B树的插入实现B树的节点设计B树的查找B树插入Key / Key & Value的过程B树的完整插入代码B树的中序遍历B树的删除B树的性能分析 五、B树六、B*树七、B树系列总结及其应用总结 前言 我们计算…...

04-stm32的标准外设库

一、概述 1、STM32标准外设库&#xff08;Standard Peripheral Library&#xff09;是STMicroelectronics为STM32系列微控制器提供的一个软件库&#xff0c;它提供了一组API函数来简化对STM32微控制器硬件的访问。这个库包含了对各种外设&#xff08;如GPIO、USART、SPI、I2C等…...

ORACLE RAC环境使用ASM机制零宕机时间更换存储的实践

ORACLE RAC使用存储&#xff0c;随时系统的发展&#xff0c;磁盘空间以及存储的老化、更换是一个典型的动作&#xff1b;基于ASM数据自动均衡分配到各个磁盘LUN的特性&#xff0c;可以使用此方式进行在线的迁移&#xff0c;ORACLE MOS上有一个文档&#xff1a;中文版&#xff1…...

03_JavaScript

文章目录 一、概述1.1、JavaScript简介1.2、JavaScript组成部分1.3、为什么要学习JavaScript1.4、学习的目的1.5、JavaScript与Java的关系 二、使用位置及运行说明2.1、使用位置2.2、如何运行 三、JavaScript基础语法3.1、变量3.2、运算符3.3、控制流程3.3.1、分支结构3.3.2、循…...

Kafka消息可视化工具Offset Explorer

参考文献 Kafka消息可视化工具&#xff1a;Offset Explorer&#xff08;原名kafka Tool&#xff09;的使用方法【转】 - paul_hch - 博客园 https://zhuanlan.zhihu.com/p/722232008 正文 官网下载地址为Offset Explorer 双击offsetexplorer_64bit.exe 安装 双击 使用kafka…...

AXP2101入门

目录 核心功能与特性封装与配置安全与可靠性 AXP2101 是一款由全志公司开发的单电池 NVDC 电源管理集成电路&#xff08;PMIC&#xff09;&#xff0c;专为锂离子/锂聚合物单电池应用设计&#xff0c;适用于需要多通道电源输出的设备。 核心功能与特性 1.输入与充电管理 输入…...

Bytebase 取得 SOC 2 Type 1 认证

我们很高兴地宣布&#xff0c;Bytebase 已成功取得 SOC 2 Type 1 认证&#xff0c;印证了我们在数据库 DevSecOps 平台始终以最高标准保障安全性、可用性和保密性的承诺。 为了实现并维持 SOC 2 合规性&#xff0c;我们与 Vanta 合作进行自动安全监控和合规性验证。审计由独立…...

反爬系列 IP 限制与频率封禁应对指南

在数据采集领域&#xff0c;IP 限制与频率封禁是反爬机制中最常见的防御手段。随着网站安全策略的升级&#xff0c;单靠传统爬虫技术已难以应对高强度的检测。本文将从反爬机制解析、实战应对策略两个维度&#xff0c;系统讲解如何突破 IP 限制与频率封禁。 一、反爬机制解析 …...

Java的进阶学习

注解 Java注解(Annotation)又称为Java标注&#xff0c;是JDK5.0引入的一种注释机制&#xff0c;可以用在类、方法、变量、参数成员上&#xff0c;在编译期间&#xff0c;会被编译到字节码文件中&#xff0c;运行时通过反射机制获得注解内容进行解析。 内置注解 Java语言已经定…...

从零开始学习SLAM|技术路线

概念 视觉SLAM&#xff08;Simultaneous Localization and Mapping&#xff09;系统中&#xff0c;整个过程通常分为 前端 和 后端 两个主要部分。前端处理的是从传感器数据&#xff08;如相机图像、激光雷达等&#xff09;中提取和处理信息&#xff0c;用于实时定位和建图&am…...

vue3:十一、主页面布局(修改顶部导航栏样式-右侧:用户信息+退出登录+全屏显示)

一、效果 完成效果,增加顶部导航栏,右侧用户信息(其中个人中心需要后续进行页面开发,这里只写了退出登录功能),以及全屏功能 二、搭建并引入右侧组件 将右侧内容封装到单独的组件,直接引入(像左侧导航条等内容也是可以做成这种形式) 1、新建右侧组件的页面 在layout中…...

车载客流记录仪简介

一、产品概述 车载客流记录仪技术是采用智能视频分析算法&#xff0c;通过人体形态特征&#xff08;头部和肩部&#xff09;及上下车的运动规律研判&#xff0c;在设定区域内分析出上下车人数数量&#xff0c;实现相关人数数据的统计和记录。能够为公共交通企业、公共交通管理…...

2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发

2025新版懒人精灵零基础安装调试lua基础UI设计交互常用方法封装项目实战项目打包安装板块-视频教程(初学者必修课) 1.懒人精灵核心API基础和lua基础视频教程&#xff1a;https://www.bilibili.com/video/BV1Vm9kYJEfM/ 其它板块教程(包含&#xff1a;对接AI、实战、插件、UI、…...

从 Java 到 Kotlin:在现有项目中迁移的最佳实践!

全文目录&#xff1a; 开篇语 1. 为什么选择 Kotlin&#xff1f;1.1 Kotlin 与 Java 的兼容性1.2 Kotlin 的优势1.3 Kotlin 的挑战 2. Kotlin 迁移最佳实践2.1 渐进式迁移2.1.1 步骤一&#xff1a;将 Kotlin 集成到现有的构建工具中2.1.2 步骤二&#xff1a;逐步迁移2.1.3 步骤…...

矩阵运营的限流问题本质上是平台与创作者之间的流量博弈

矩阵运营的限流问题本质上是平台与创作者之间的流量博弈&#xff0c;要系统性解决这一问题&#xff0c;需从技术规避、内容优化、运营策略三个维度构建防御体系。以下结合平台算法逻辑与实战案例&#xff0c;深度解析限流成因及破解之道&#xff1a; 一、技术层&#xff1a;突…...

一种Spark程序运行指标的采集与任务诊断实现方式

一种Spark程序运行指标的采集与任务诊断实现方式 编写时间:2023年8月2日 第一次校准时间:2023年8月2日 文章目录 一种Spark程序运行指标的采集与任务诊断实现方式数据链路采集器的类图CustomSparkListener采集的指标task相关stage相关Job相关Executors相关诊断诊断分类调度阶…...

Gazebo 仿真环境系列教程(一):环境安装与基础使用

文章目录 一、版本说明与技术背景1.1 Gazebo 版本分支1.2 版本选择建议 二、系统环境准备2.1 硬件要求2.2 软件依赖 三、Gazebo Garden 安装流程3.1 添加官方软件源3.2 执行安装命令3.3 环境验证 四、Gazebo Classic 安装方法4.1 添加软件仓库4.2 安装核心组件4.3 验证安装 五、…...

Nginx 中间件

Nginx&#xff08;发音为 "engine-x"&#xff09;是一款开源的高性能 HTTP 服务器和反向代理服务器&#xff0c;最初由 Igor Sysoev 开发。 它以其高性能、稳定性、丰富的功能集和低资源消耗而闻名&#xff0c;广泛应用于全球的 Web 服务架构中。 作为中间件&#…...

记录学习的第三十一天

今天只做了一道每日一题。 说实话&#xff0c;根本不会做呀&#xff0c;该怎么办&#xff1f; 以下是我看了题解之后的思路(适合新手&#xff09;&#xff1a; 1.首先肯定是要求出整个数组的不同数字有多少个的使用set来操作 2.右指针开始进入窗口&#xff0c;把元素放进哈希…...

Framework.jar里的类无法通过Class.forName反射某个类的问题排查

1&#xff0c;背景 我们想要在system_server进程里扩展一些我们自己的功能。 考虑到解耦和编译依赖的问题&#xff0c;我们用PRODUCT_SYSTEM_SERVER_JARS预置我们的类&#xff0c;然后用反射jar里面的类的方式来实现代码引用。 2&#xff0c;遇到的问题 在SystemServer.jav…...

架构-信息安全技术基础知识

一、信息安全基础 1. 信息安全的5个基本要素&#xff08;重点&#xff09; 机密性&#xff1a;确保信息不泄露给未授权的人或程序。 ▶ 举例&#xff1a;银行用户的账户密码必须保密&#xff0c;防止黑客窃取。完整性&#xff1a;保证信息不被非法修改&#xff0c;保持准确和…...

项目班——0419——chrono时间库

1、写日志需要时间库 C11时间库chrono源自于boost 1.时间间隔 duration 2.时间点 timepoint 3.时钟 clock 系统时钟system_clock&#xff0c;稳定时钟steady_clock&#xff0c;高精度时钟high_resolution_clock 例子 1、休眠100毫秒 2、输出当前时间 获取当前时间戳 s…...

Unity后处理全解析:从入门到优化

在游戏开发的世界里,Unity作为一款强大的游戏引擎,为开发者们提供了丰富的功能和工具。其中,后处理(Post-Processing)技术是提升游戏画面质量和视觉效果的重要手段之一。今天,我们就来深入探讨一下Unity后处理的相关内容,包括基本概念、使用说明、常见效果、优化技巧以及…...

得物业务参数配置中心架构综述

一、背景 现状与痛点 在目前互联网飞速发展的今天&#xff0c;企业对用人的要求越来越高&#xff0c;尤其是后端的开发同学大部分精力都要投入在对复杂需求的处理&#xff0c;以及代码架构&#xff0c;稳定性的工作中&#xff0c;在对比下&#xff0c;简单且重复的CRUD就显得…...

针对密码学的 EM 侧信道攻击

基于电磁的侧信道攻击是非侵入式的,这意味着攻击者无需物理接触设备即可窃取信息。我们将了解这些电磁侧信道攻击的工作原理。 我们之前介绍了侧信道攻击的概念:它们是什么,以及为什么它们会成为重大的硬件安全威胁。在众多形式的侧信道攻击中,最强大的一种是电磁 (EM) 攻…...

el-setup- 修改样式(vue3)

一 第一步 <template><el-steps :active"activeStep" align-center><el-stepv-for"item in stepData":key"item.value":class"{ currentStep: activeStep item.value }"><template #icon><div class"…...

CPT204 Advanced Obejct-Oriented Programming 高级面向对象编程 Pt.8 排序算法

文章目录 1. 排序算法1.1 冒泡排序&#xff08;Bubble sort&#xff09;1.2 归并排序&#xff08;Merge Sort&#xff09;1.3 快速排序&#xff08;Quick Sort&#xff09;1.4 堆排序&#xff08;Heap Sort&#xff09; 2. 在面向对象编程中终身学习2.1 记录和反思学习过程2.2 …...