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

缓存设计模式

缓存设计模式(Cache Design Pattern)是一种用于存储和管理频繁访问数据的技术,旨在提高系统性能、降低数据库或后端服务的负载,并减少数据访问延迟。以下是几种常见的缓存设计模式,并用 Python + Redis 进行示例代码实现:


📌 1. Cache Aside(旁路缓存)

🌟 适用场景:

  • 适用于读多写少的场景,如商品详情、用户资料等。
  • 应用先从缓存中读取数据,缓存未命中时再查询数据库,并将数据写入缓存。

📝 逻辑流程:

  1. 先查询缓存,如果命中,则直接返回数据。
  2. 如果缓存未命中,则查询数据库,并将查询结果写入缓存。
  3. 返回数据库查询的数据。

🚀 代码示例

import redis
import timeredis_client = redis.StrictRedis(host="localhost", port=6379, decode_responses=True)def get_data_cache_aside(key):cache_key = f"cache:{key}"# Step 1: 先查询缓存data = redis_client.get(cache_key)if data:return data  # 直接返回缓存数据# Step 2: 缓存未命中,查询数据库data = query_database(key)# Step 3: 回填缓存if data:redis_client.setex(cache_key, 60, data)  # 缓存 60sreturn datadef query_database(key):"""模拟数据库查询"""time.sleep(1)  # 模拟查询时间return f"data_for_{key}"# 测试
print(get_data_cache_aside("hot_item"))

存在的问题:旁路缓存(Cache Aside)如果数据库中的数据为空(例如,数据确实不存在或者被删除了),那么每次查询都会缓存未命中,导致系统一直查数据库,这就是缓存穿透(Cache Penetration)问题。

🎯 解决方案

方案 1:缓存空值

  • 思路:如果数据库查询结果为空,则缓存一个“空值”(如 null 或特殊占位符),并设置较短的 TTL(如 5~10 秒)。
  • 好处:防止短时间内同一个 Key 反复查询数据库。
🔹 改进的旁路缓存代码
import redis
import timeredis_client = redis.StrictRedis(host="localhost", port=6379, decode_responses=True)def get_data_cache_aside(key):cache_key = f"cache:{key}"# Step 1: 查询缓存data = redis_client.get(cache_key)if data is not None:  # 即使数据为空(缓存的空值),也不会去数据库查询return None if data == "NULL" else data# Step 2: 查询数据库data = query_database(key)# Step 3: 数据为空,缓存“空值”并设置较短过期时间if data is None:redis_client.setex(cache_key, 10, "NULL")  # 10秒缓存空值,避免短时间重复查库return None# Step 4: 数据有效,回填缓存redis_client.setex(cache_key, 60, data)  # 60秒缓存数据return datadef query_database(key):"""模拟数据库查询"""time.sleep(1)  # 模拟数据库查询时间return None  # 假设数据不存在# 测试
print(get_data_cache_aside("hot_item"))  # 第一次查数据库
print(get_data_cache_aside("hot_item"))  # 直接命中缓存(返回 None,不查数据库)

效果

  • 第一次查询,数据库返回 None,缓存 "NULL" 并设置 10 秒过期。
  • 10 秒内相同的 Key 再次查询时,直接返回 None不会重复访问数据库
  • 10 秒后,缓存过期,才会重新查询数据库。

方案 2:布隆过滤器(Bloom Filter)

  • 思路:使用布隆过滤器(Bloom Filter)提前判断数据是否存在,不存在的 Key 直接返回 None,不查询数据库。
  • 适用场景:大规模 Key 查询,如用户 ID、商品 ID
🔹 代码示例
from bloom_filter import BloomFilter  # 需要安装 pip install bloom-filter2# 初始化布隆过滤器(假设有 10 万个 Key,误判率 0.01)
bloom = BloomFilter(max_elements=100000, error_rate=0.01)# 预先加入一些存在的 Key
bloom.add("valid_key_1")
bloom.add("valid_key_2")def get_data_bloom_filter(key):cache_key = f"cache:{key}"# Step 1: 先检查布隆过滤器,数据可能不存在if key not in bloom:return None  # 直接返回,不查数据库# Step 2: 查询缓存data = redis_client.get(cache_key)if data is not None:return None if data == "NULL" else data# Step 3: 查询数据库data = query_database(key)# Step 4: 缓存数据或空值if data is None:redis_client.setex(cache_key, 10, "NULL")return Noneredis_client.setex(cache_key, 60, data)return data# 测试
print(get_data_bloom_filter("invalid_key"))  # 布隆过滤器拦截,直接返回 None
print(get_data_bloom_filter("valid_key_1"))  # 查询缓存或数据库

效果

  • 布隆过滤器拦截不存在的数据,避免数据库查询
  • 误判率极低(0.01%),但不会产生误漏。

方案 3:限流 & 黑名单

  • 思路:针对异常高频查询某个 Key 的请求,可以加入限流机制黑名单,防止恶意攻击导致数据库压力过大。
🔹 代码示例
from collections import defaultdictrequest_count = defaultdict(int)def get_data_with_rate_limit(key):cache_key = f"cache:{key}"# Step 1: 统计 Key 查询次数request_count[key] += 1if request_count[key] > 100:  # 限制单个 Key 短时间内查询次数return "Too Many Requests"  # 直接拒绝请求# Step 2: 查询缓存data = redis_client.get(cache_key)if data is not None:return None if data == "NULL" else data# Step 3: 查询数据库data = query_database(key)# Step 4: 缓存数据或空值if data is None:redis_client.setex(cache_key, 10, "NULL")return Noneredis_client.setex(cache_key, 60, data)return data

效果

  • 限制某个 Key 频繁查询,避免恶意攻击导致数据库崩溃。
  • 结合 IP 级别限流,进一步防护。

📌 总结

方案适用场景优势缺点
缓存空值任何缓存穿透情况简单高效,防止短时间重复查询额外占用 Redis 空间
布隆过滤器大量 Key 查询,如用户 ID、商品 ID高效过滤无效 Key,减少数据库压力需要额外存储布隆过滤器
限流 & 黑名单恶意攻击、异常高频请求防止恶意攻击,减少数据库压力需要额外维护限流规则

🚀 推荐方案组合

  • 一般情况:✅ 缓存空值
  • 海量 Key 级别:✅ 布隆过滤器 + 缓存空值
  • 防恶意攻击:✅ 限流 & 黑名单

这样可以有效防止缓存穿透,保护数据库不被高并发打崩!🔥

📌 2. Read-Through(读穿透)

🌟 适用场景:

  • 适用于需要自动填充缓存的情况,例如 CDN、NoSQL 代理等。
  • 读请求永远只访问缓存,如果缓存未命中,由缓存层自动加载数据。

📝 逻辑流程:

  1. 读取数据时,应用程序只访问缓存。
  2. 如果缓存未命中,则缓存层自动从数据库加载数据并缓存
  3. 数据返回给用户。

🚀 代码示例

class Cache:def __init__(self):self.redis_client = redis.StrictRedis(host="localhost", port=6379, decode_responses=True)def get(self, key):"""从缓存读取数据"""data = self.redis_client.get(key)if not data:data = self.load_from_db(key)  # 由缓存层自动加载self.redis_client.setex(key, 60, data)  # 缓存 60sreturn datadef load_from_db(self, key):"""模拟数据库查询"""time.sleep(1)  # 模拟查询时间return f"data_for_{key}"# 测试
cache = Cache()
print(cache.get("hot_item"))

存在的问题:读穿透(Read-Through)同样可能会遇到类似的缓存穿透问题。如果缓存未命中且查询结果为空(例如,数据库中没有该数据),那么每次查询都会去数据库查询,造成重复查询数据库的情况。

🎯 解决方案

与旁路缓存的解决方案一致


📌 3. Write-Through(写穿透)

🌟 适用场景:

  • 适用于写多读少的情况,如用户状态、计数器等。
  • 所有写操作都会先更新缓存,然后再更新数据库,确保缓存和数据库的一致性。

📝 逻辑流程:

  1. 当数据写入时,先更新缓存,再更新数据库。
  2. 读请求仍然直接从缓存读取数据。

🚀 代码示例

class Cache:def __init__(self):self.redis_client = redis.StrictRedis(host="localhost", port=6379, decode_responses=True)def set(self, key, value):"""写入缓存 + 数据库"""self.redis_client.setex(key, 60, value)  # 先写入缓存self.write_to_db(key, value)  # 再写入数据库def get(self, key):"""读取缓存"""return self.redis_client.get(key)def write_to_db(self, key, value):"""模拟数据库写入"""print(f"数据 {key} 已写入数据库: {value}")# 测试
cache = Cache()
cache.set("user:123", "UserData")
print(cache.get("user:123"))

存在问题
一致性问题:缓存和数据库可能在短时间内处于不同步的状态。例如,如果缓存成功写入,但数据库写入失败,数据就不一致了。为了避免这种情况,你可能需要引入一些机制来确保最终一致性,如 异步写入 或 消息队列 来处理数据库更新

错误处理和重试:如果数据库写入失败,如何处理这个问题是一个关键点。可以考虑将数据库写入操作异步化,或者通过定期的任务检查数据一致性并做修复。


📌 4. Write-Behind(异步写回)

🌟 适用场景:

  • 适用于高并发写入,如日志存储、计数器等。
  • 先写入缓存,异步批量更新数据库,提高写入性能。

📝 逻辑流程:

  1. 写操作只写入缓存,不直接更新数据库。
  2. 后台异步线程定期批量同步缓存数据到数据库

🚀 代码示例

import threadingclass Cache:def __init__(self):self.redis_client = redis.StrictRedis(host="localhost", port=6379, decode_responses=True)self.batch_data = {}  # 临时存储待写入的数据def set(self, key, value):"""写入缓存"""self.redis_client.setex(key, 60, value)  # 先写入缓存self.batch_data[key] = value  # 添加到待写入数据库的批量任务def get(self, key):"""读取缓存"""return self.redis_client.get(key)def batch_write_to_db(self):"""批量写入数据库(定期执行)"""while True:if self.batch_data:for key, value in self.batch_data.items():print(f"批量写入数据库: {key} -> {value}")self.batch_data.clear()time.sleep(5)  # 每 5 秒写入一次# 启动异步写线程
cache = Cache()
threading.Thread(target=cache.batch_write_to_db, daemon=True).start()# 测试
cache.set("user:123", "UserData")
cache.set("user:124", "UserData2")
print(cache.get("user:123"))
time.sleep(6)  # 等待异步写入数据库

📌 5. 分布式锁(Mutex + Double Check)

🌟 适用场景:

  • 解决缓存击穿问题,防止多个线程同时查询数据库。
  • 适用于高并发的热点数据,如商品详情、排行榜等。

📝 逻辑流程:

  1. 先查询缓存,如果命中,则直接返回数据。
  2. 如果缓存未命中,尝试获取 Redis 互斥锁
    • 获取锁成功:查询数据库,并回填缓存,最后释放锁。
    • 获取锁失败:等待一段时间后重试,避免并发查询数据库。

🚀 代码示例

import uuiddef get_data_with_mutex(key):cache_key = f"cache:{key}"lock_key = f"lock:{key}"lock_value = str(uuid.uuid4())# 先查询缓存data = redis_client.get(cache_key)if data:return data# 尝试获取锁if redis_client.set(lock_key, lock_value, nx=True, ex=5):  try:# 再次检查缓存data = redis_client.get(cache_key)if data:return data# 查询数据库data = query_database(key)# 回填缓存redis_client.setex(cache_key, 60, data)return datafinally:if redis_client.get(lock_key) == lock_value:redis_client.delete(lock_key)else:# 其他线程等待后重试time.sleep(0.2)return get_data_with_mutex(key)# 测试
print(get_data_with_mutex("hot_item"))

🎯 总结

设计模式适用场景主要特点
Cache Aside读多写少业务代码控制缓存逻辑
Read-Through读写频繁读请求只访问缓存,自动回填
Write-Through写多读少写请求先更新缓存,再写数据库
Write-Behind高并发写先写缓存,异步批量写数据库
分布式锁缓存击穿互斥锁防止多个线程并发查询数据库

不同的缓存模式可以根据实际的业务需求和系统架构进行组合使用。组合的依据主要取决于以下几个因素:

1. 一致性要求

不同缓存模式的选择和组合通常取决于对数据一致性的要求:

  • 强一致性:如果你需要确保缓存和数据库的严格一致性,可以使用 写缓存(Write-Through Cache),确保每次数据写入时,缓存和数据库同步更新。这可以保证数据库和缓存中的数据始终一致。
  • 最终一致性:如果你可以接受数据暂时的不一致(例如稍微过期或延迟同步),可以考虑使用 写回缓存(Write-Back Cache),将数据先写入缓存,异步地将数据写入数据库,从而减少对数据库的压力。

2. 数据读取频率与缓存容量

  • 高读取频率、低写入频率:如果应用程序主要是读取数据,且数据不经常变化,可以使用 读缓存(Read-Through Cache)旁路缓存(Cache-Aside)。通过将热点数据加载到缓存中,减少对数据库的查询压力。
  • 高写入频率、低读取频率:如果写操作频繁,但读取较少(如日志系统),可以考虑 写回缓存(Write-Back Cache),这样可以减少对数据库的写入频率,提高性能。

3. 缓存失效策略

  • 过期时间(TTL):某些数据可能会在一定时间后过期,可以结合 过期缓存(TTL) 策略使用。例如,你可以在使用 旁路缓存(Cache-Aside) 时设置一个缓存过期时间,确保缓存中不存储过时数据,同时保证不频繁查询数据库。
  • 清除策略:结合 LRU(Least Recently Used) 等缓存淘汰策略,当缓存容量达到上限时,移除不常用的数据。

4. 缓存失效和更新策略

  • 缓存雪崩(Cache Avalanche):当大量缓存同时失效时,可能导致大量请求直接打到数据库上,造成压力。通过 设置不同的过期时间分布式缓存策略,可以避免缓存雪崩现象。组合使用 缓存分片(Sharded Cache)缓存预热 等方式,有助于平衡缓存更新带来的负担。

  • 缓存穿透(Cache Penetration):如果某些数据根本不在缓存中(例如查询不存在的用户信息),则每次都会访问数据库。可以通过 布隆过滤器(Bloom Filter) 或其他方式来过滤这些请求,减少数据库压力。

5. 性能与可扩展性需求

  • 分布式缓存:如果系统需要高可扩展性,可以使用 分布式缓存(Sharded Cache),将数据分片存储到多个缓存节点中,保证高并发时的缓存命中率,同时避免单个缓存节点的负载过高。
  • 异步缓存更新:可以使用消息队列或后台任务来异步更新缓存和数据库,避免在请求处理过程中进行阻塞操作。

常见的缓存模式组合

组合 1:读缓存(Read-Through Cache) + 过期缓存(TTL)
  • 适用场景:读取频繁、数据变化不大。
  • 组合原因:缓存数据可以在一段时间后过期,从而确保缓存不存储过时的数据,同时不需要每次都查询数据库。
def read_through_with_ttl(key):value = cache.get(key)if value is None:value = db.get(key)cache.set(key, value, ex=3600)  # 1 小时后过期return value
组合 2:旁路缓存(Cache-Aside) + LRU 淘汰策略
  • 适用场景:数据访问较不频繁,但需要缓存热点数据。
  • 组合原因:通过 LRU 策略确保缓存中存储的始终是最近访问的数据,而不需要每次都清理整个缓存。
def cache_aside_lru(key):value = cache.get(key)if value is None:value = db.get(key)cache.set(key, value)return value
组合 3:写回缓存(Write-Back Cache) + 过期缓存(TTL)
  • 适用场景:写入频繁,且数据库更新不需要立刻完成。
  • 组合原因:缓存首先写入,而后台异步更新数据库,同时使用缓存过期时间,确保不存储过时的数据。
def write_back_with_ttl(key, value):cache.set(key, value)  # 先写缓存write_queue.append((key, value))  # 异步写数据库cache.expire(key, 3600)  # 设置过期时间
组合 4:分片缓存(Sharded Cache) + 写回缓存(Write-Back Cache)
  • 适用场景:数据量巨大,且需要分布式缓存支持。
  • 组合原因:将缓存数据分布到不同的节点,并且使用写回缓存减少数据库访问频率,提高系统性能。

总结

缓存模式组合的依据主要取决于你的应用场景,特别是数据一致性要求、性能需求、读取/写入频率、以及缓存过期策略等因素。在实际开发中,可以根据具体的需求灵活选择或组合这些模式,以达到最佳的系统性能和数据一致性。

相关文章:

缓存设计模式

缓存设计模式(Cache Design Pattern)是一种用于存储和管理频繁访问数据的技术,旨在提高系统性能、降低数据库或后端服务的负载,并减少数据访问延迟。以下是几种常见的缓存设计模式,并用 Python Redis 进行示例代码实现…...

详解TCP的四次握手和三次挥手,以及里面每个阶段的状态

TCP 三次握手(连接建立) TCP 连接建立通过三次握手完成,确保双方同步初始序列号并确认可达性。 阶段说明 第一次握手 客户端 → 服务器:发送 SYN(同步请求),携带初始序列号 seq x。客户端状态…...

Linux文件目录管理指令详解(上篇)

Linux文件目录管理指令详解(上篇) 在Linux操作系统中,文件目录管理是基础且重要的技能。通过一系列指令,用户可以高效地浏览、创建、修改和删除文件及目录。本文将详细介绍Linux中常用的文件目录管理类指令,包括pwd、…...

BCC-应用程序组件分析

libbpf-tools/gethostlatency 追踪glibc中的getaddrinfo、gethostbyname、gethostbyname2函数用时 # /usr/share/bcc/libbpf-tools/gethostlatency TIME PID COMM LATms HOST 14:58:32 8418 curl 313.635 www.taobao.com以# cur…...

无参数读文件和RCE

什么是无参数? 无参数(No-Argument)的概念,顾名思义,就是在PHP中调用函数时,不传递任何参数。我们需要利用仅靠函数本身的返回值或嵌套无参数函数的方式,达到读取文件或远程命令执行&#xff0…...

SpringMVC_day02

一、SSM 整合 核心步骤 依赖管理 包含 SpringMVC、Spring JDBC、MyBatis、Druid 数据源、Jackson 等依赖。注意点:确保版本兼容性(如 Spring 5.x 与 MyBatis 3.5.x)。 配置类 SpringConfig:扫描 Service 层、启用事务管理、导入…...

在Linux、Windows系统上安装开源InfluxDB——InfluxDB OSS v2并设置开机自启的保姆级图文教程

一、进入InfluxDB下载官网 InfluxData 文档https://docs.influxdata.com/Install InfluxDB OSS v2 | InfluxDB OSS v2 Documentation...

LinkedIn数据抓取零风险指南:亮数据住宅代理实现企业级合规采集

亮数据住宅代理实现企业级合规采集 一、前言二、尝试使用三、使用体验高效稳定易用性:合规与安全:技术支持: 四、适用场景五、推荐程度六、试用地址 一、前言 最近一位猎头小伙伴找到我,说目前很多公司的出海业务都在招人&#x…...

ROS2的发展历史、核心架构和应用场景

以下是对**ROS2(Robot Operating System 2)**的发展历史、核心架构和应用场景的详细解析,覆盖其技术演变、关键特性和生态系统: 一、ROS2的诞生背景:从ROS1到ROS2 1. ROS1的历史与局限 ROS1的起源: 2007年…...

PHP eval 长度限制绕过与 Webshell 获取

在 PHP 代码中&#xff0c;如果 eval($param); 存在且长度受限&#xff0c;并且过滤了 eval 和 assert&#xff0c;仍然可以通过多种方法绕过限制&#xff0c;获取 Webshell。 源码 <?php $param $_REQUEST[param]; if(strlen($param)<17 && stripos($param,…...

自然语言处理(14:处理时序数据的层的实现)

系列文章目录 第一章 1:同义词词典和基于计数方法语料库预处理 第一章 2:基于计数方法的分布式表示和假设&#xff0c;共现矩阵&#xff0c;向量相似度 第一章 3:基于计数方法的改进以及总结 第二章 1:word2vec 第二章 2:word2vec和CBOW模型的初步实现 第二章 3:CBOW模型…...

Pytest的Fixture使用

概述 Pytest中的Fixture可以使得测试代码高度复用,同时对资源进行安全的管理,以及在复杂的测试场景用进行灵活的组合。 概念 Fixture:可重用的函数,用@pytest.fixture来进行装饰,用于为测试提供数据、环境或者服务作用域:控制Fixture的生命周期,默认是function,可设置…...

【蓝桥杯】每日练习 Day13

前言 今天做了不少题&#xff0c;但是感觉都太水了&#xff0c;深思熟虑之下主播决定拿出两道相对不那么水的题来说一下&#xff08;其实还是很水&#xff09;。 两道问题&#xff0c;一道是日期问题&#xff08;模拟&#xff09;&#xff0c;一道是区间合并问题。 日期差值 …...

Vue3 中使用 vuedraggable 实现拖拽排序功能,分组拖拽

Vue3 中使用 vuedraggable 实现拖拽排序功能&#xff0c;分组拖拽 安装draggable npm install vuedraggablenext --save基础用法示例 <template><div class"app-container"><draggable v-model"list" item-key"id":group"…...

husky的简介以及如果想要放飞自我的解决方案

husky 是一个 Git Hooks 管理工具&#xff0c;它的主要作用是 在 Git 提交&#xff08;commit&#xff09;、推送&#xff08;push&#xff09;等操作时执行自定义脚本&#xff0c;比如代码检查&#xff08;Lint&#xff09;、单元测试&#xff08;Test&#xff09;、格式化代码…...

Maven工具学习使用(四)——仓库

仓库分类 对于Mavne来说,仓库只分为两类:本地仓库和远程仓库。当Maven根据坐标查询寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在此构件,则直接使用;如果本地仓库不存在此构件,或者需要查看是否有更新的构件版本,Maven就会去远程仓库查找,发现需要的构件之后…...

【BFS】《单源、多源 BFS:图搜索算法的双生力量》

文章目录 前言单源BFS例题一、迷宫中离入口最近的出口二、 最小基因变化三、单词接龙四、为高尔夫比赛砍树 多源BFS例题一、 01 矩阵二、飞地的数量三、地图中的最高点四、地图分析 结语 前言 什么是单源、多源BFS算法问题呢&#xff1f; BFS&#xff08;Breadth - First Sear…...

批量取消 PDF 文档中的所有超链接

在 PDF 文档中我们可以插入各种各样的文本也可以给文本设置字体&#xff0c;颜色等多种样式&#xff0c;同时还可以给文字或者图片添加上超链接&#xff0c;当我们点击超链接之后&#xff0c;就会跳转到对应的网页。有时候这会对我们的阅读或者使用形成一定的干扰&#xff0c;今…...

13.2 kubelet containerRuntime接口定义和初始化

本节重点总结 &#xff1a; containerRuntime 需要实现3类接口 管理容器的接口管理镜像的接口Streaming API 用于客户端与容器进行交互 type KubeGenericRuntime interface {kubecontainer.Runtimekubecontainer.StreamingRuntimekubecontainer.CommandRunner }containerRun…...

使用 gone.WrapFunctionProvider 快速接入第三方服务

项目地址&#xff1a;https://github.com/gone-io/gone 本文中源代码&#xff1a; esexamples/es 文章目录 1. gone.WrapFunctionProvider 简介2. 配置注入实现3. 实战示例&#xff1a;Elasticsearch 集成4. 使用方式5. 最佳实践6. 总结 在如何给Gone框架编写Goner组件&#xf…...

git 标签学习笔记

目录 轻量级标签 带注释的标签&#xff08;推荐&#xff09; 给指定 commit 打标签 推送单个标签&#xff0c;需要单独推送&#xff0c;代码推送不会推送标签 推送所有标签 删除标签 轻量级标签 git tag v1.0.0 只是简单地给当前 commit 打上 v1.0.0 标签。 带注释的标…...

【论文阅读】基于思维链提示的大语言模型软件漏洞发现与修复方法研究

这篇文章来自于 Chain-of-Thought Prompting of Large Language Models for Discovering and Fixing Software Vulnerabilities 摘要 软件安全漏洞在现代系统中呈现泛在化趋势&#xff0c;其引发的社会影响日益显著。尽管已有多种防御技术被提出&#xff0c;基于深度学习&…...

企业在人工智能创新与安全之间走钢丝

2025 年全球 AI/ML 工具使用量将激增&#xff0c;企业将 AI 融入运营之中&#xff0c;员工也将 AI 嵌入日常工作流程中。报告显示&#xff0c;企业对 AI/ML 工具的使用同比增长 3,000% 以上&#xff0c;凸显了各行各业迅速采用 AI 技术&#xff0c;以提升生产力、效率和创新水平…...

CSS动画

目录 一、核心概念与语法 1. keyframes 关键帧 2. animation 属性 二、动画调速函数&#xff08;animation-timing-function&#xff09; 1. 预设值 2. 贝塞尔曲线 3. 步进函数&#xff08;steps()&#xff09; 三、动画控制与交互 1. 暂停与恢复 2. JavaScript 控制…...

计算机视觉(CV)技术的优势和挑战

计算机视觉&#xff08;CV&#xff09;技术是人工智能领域中的一个重要分支&#xff0c;它主要通过让机器学会“看”和“理解”图像或视频来模拟人类视觉系统。以下是计算机视觉技术的一些优势和挑战&#xff1a; 优势&#xff1a; 自动化&#xff1a;计算机视觉技术可以实现…...

动态IP与静态IP该如何选?

一、当IP地址成为"网络身份" 2023年亚马逊封号潮中&#xff0c;某杭州卖家因登录IP频繁切换&#xff08;早8点在纽约&#xff0c;午间瞬移到东京&#xff09;&#xff0c;触发平台风控导致账号冻结。这类"时空错乱症"揭示了跨境电商的生存法则&#xff1a…...

Vue.js 完全指南:从入门到精通

1. Vue.js 简介 1.1 什么是 Vue.js? Vue.js(通常简称为 Vue)是一个用于构建用户界面的渐进式 JavaScript 框架。所谓"渐进式",意味着 Vue 的设计是由浅入深的,你可以根据自己的需求选择使用它的一部分或全部功能。 Vue 最初由尤雨溪(Evan You)在 2014 年创…...

《TypeScript 7天速成系列》第3天:TypeScript高级类型通关秘籍:泛型+联合+交叉类型实战

TypeScript 的类型系统是其最强大的特性之一&#xff0c;但也是许多开发者感到困惑的地方。今天我们就来破解 TypeScript 中最难的类型系统&#xff0c;掌握泛型、联合类型和交叉类型的使用技巧。 一、泛型函数与泛型接口 泛型是 TypeScript 中创建可重用组件的重要工具&…...

Python----数据分析(足球运动员数据分析)

一、数据展示 1.1、数据 1.2、列名 字段名备注Name姓名Nationality国籍National_Position国家队位置National_Kit国家队号码Club所在俱乐部Club_Position所在俱乐部位置Club_Kit俱乐部号码Club_Joining加入俱乐部时间Contract_Expiry合同到期时间Rating评分Height身高Weight体…...

音视频 三 看书的笔记 MediaPlayer的C/S架构

MediaPlayer在运行时分为Client和Server两部分 Client层‌&#xff1a;位于Java层&#xff0c;用户通过调用Java层的API&#xff08;如setDataSource&#xff09;来操作MediaPlayer。 Server层‌&#xff1a;位于C层&#xff0c;负责实际的媒体处理工作。Server层通过Binder机…...

Elasticsearch:使用 AI SDK 和 Elastic 构建 AI 代理

作者&#xff1a;来自 Elastic Carly Richmond 你是否经常听到 AI 代理&#xff08;AI agents&#xff09;这个词&#xff0c;但不太确定它们是什么&#xff0c;或者如何在 TypeScript&#xff08;或 JavaScript&#xff09;中构建一个&#xff1f;跟我一起深入了解 AI 代理的概…...

echarts添加坐标轴点击事件

echarts添加坐标轴点击事件 chart.on(click, (params) > {if(params.componentType yAxis && this.type ! 1){console.log(params);// 检查是否点击了系列数据console.log(你点击了 ${params.name} 的数据点&#xff0c;值为 ${params.value}); this.$bus.$emi…...

如何在linux中部署dns服务 主备dns (详细全过程)

环境centos 7.9 主DNS&#xff1a;192.168.60.131 备DNS&#xff1a;192.168.60.134 我以 chenxingyu0.com 指向 192.168.60.200为例 首先是主dns #!/bin/bash# 检查是否为 root 用户 if [ "$(id -u)" ! "0" ]; thenecho "请使用…...

GitLab 中文版17.10正式发布,27项重点功能解读【二】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…...

matplotlib——南丁格尔玫瑰

南丁格尔玫瑰图&#xff08;Nightingale Rose Chart&#xff09;&#xff0c;是一种特殊形式的柱状图&#xff0c;它以南丁格尔&#xff08;Florence Nightingale&#xff09;命名&#xff0c;她在1858年首次使用这种图表来展示战争期间士兵死亡原因的数据。 它将数据绘制在极坐…...

WPF 与 C# 融合开发:从基础到高级应用(一)

WPF 与 C# 融合开发&#xff1a;从基础到高级应用 一、C# 语言基础回顾 1.1 C# 语言概述 C# 是微软开发的一种现代、面向对象的编程语言&#xff0c;它融合了 C、C 和 Java 等语言的优点&#xff0c;具有简洁、安全、高效等特点。C# 广泛应用于 Windows 平台的应用开发&…...

ref和reactive区别

在 Vue 3 中&#xff0c;ref 和 reactive 是两种创建响应式数据的主要 API&#xff0c;但它们的适用场景和使用方式有所不同。以下是它们的核心区别和示例&#xff1a; 一、核心区别 特性refreactive适用数据类型所有类型&#xff08;基本类型、对象、数组&#xff09;仅对象或…...

精选10个好用的WordPress免费主题

10个好用的WordPress免费主题 1. Astra Astra 是全球最受欢迎的 WordPress 主题。它功能丰富&#xff0c;易于使用&#xff0c;SEO友好&#xff0c;是第一个安装量突破100万的非默认主题&#xff0c;并获得了5000多个五星好评。 它完美集成了Elementor、Beaver&#xff0c;古…...

DerpNStink: 1靶场渗透

DerpNStink: 1 来自 <DerpNStink: 1 ~ VulnHub> 1&#xff0c;将两台虚拟机网络连接都改为NAT模式 2&#xff0c;攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.182&#xff0c;靶场IP192.168.23.213 3&#xff0c;对靶机进行端…...

apache安装脚本使用shell建立

注意防火墙&#xff0c;yum&#xff0c;网络连接等 以下是具体的apache安装脚本 #!/bin/bash # Set Apache version to install ## author: yuan # 检查外网连接 echo "检查外网连接..." ping www.baidu.com -c 3 > /dev/null 2>&1 if [ $? -eq 0 ]; …...

Azure SDK 使用指南

​Azure SDK&#xff08;软件开发工具包&#xff09;是一组由微软提供的工具和库&#xff0c;旨在帮助开发者以多种编程语言&#xff08;如 .NET、Java、Python、JavaScript 等&#xff09;与 Azure 服务进行交互。 ​通过使用 Azure SDK&#xff0c;开发者可以更高效地构建、部…...

DeepSeek-V3-0324 版本升级概要

DeepSeek-V3-0324 魔搭社区汇聚各领域最先进的机器学习模型&#xff0c;提供模型探索体验、推理、训练、部署和应用的一站式服务。https://modelscope.cn/models/deepseek-ai/DeepSeek-V3-0324 发布背景与改进 根DeepSeek-V3-0324 展示了以下关键改进&#xff1a; 推理性能提…...

leetcode 150. 逆波兰表达式求值

150. 逆波兰表达式求值 - 力扣&#xff08;LeetCode&#xff09; class Solution:def evalRPN(self, tokens: List[str]) -> int:stack[]for item in tokens:if item not in ( ,-,* , / ):stack.append(item)else:preint(stack.pop())pre_beforeint(stack.pop())sign itemi…...

LangChain4j与DashScope深度集成实战:一站式开发指南

本篇文章会通篇详细的讲清楚LangChain4j与DashScope集成的各个方面&#xff0c;从Springboot的集成到Ai对话、会话记忆、RAG、FunctionCalling、互联网搜索、结构化的输出、多模态等都给出相应的说明&#xff0c;希望通过这篇文章对于LLM不了解的同仁一样可以扩展出自己的AI应用…...

逼用户升级Win11,微软开始给Win10限速

随着Windows10的支持时间越来越短&#xff0c;微软也加大了对Win10用户的驱赶力度。 最近&#xff0c;微软官宣了将要在今年6月份降低OneNote for Windows 10的同步速度。软件也将和Windows10在今年的10月14日一同停止支持和维护。 这将影响实时协作和多设备访问。 对OneNote…...

工作流引擎Flowable介绍及SpringBoot整合使用实例

Flowable简介 Flowable 是一个轻量级的业务流程管理&#xff08;BPM&#xff09;和工作流引擎&#xff0c;基于 Activiti 项目发展而来&#xff0c;专注于提供高性能、可扩展的工作流解决方案。它主要用于企业级应用中的流程自动化、任务管理和审批流等场景。 Flowable 的核心…...

推荐一个可以自定义github主页的网站

一、简介 Profile Readme Generator 是一个开源工具&#xff0c;可以帮助你快速创建个性化的 GitHub 个人简介&#xff08;README&#xff09;。它支持自定义内容和样式&#xff0c;让你的 GitHub 个人主页更加美观和专业。 二、使用步骤 &#xff08;一&#xff09;访问网站…...

【R语言可视化】相关系数热图

目录 热图无显著性 结果展示01&#xff1a; 热图显著性 结果展示02&#xff1a; ggplot2绘制三角热图 结果展示03&#xff1a; corrplot绘制三角热图 结果展示04: 热图无显著性 # 示例数据 data(mtcars) df <- mtcars# 计算相关矩阵 cor_matrix <- round(cor(df…...

【区块链 + 文化版权】文创链 | FISCO BCOS 应用案例

“文创链”是由四川省区块链行业协会、成都音像出版社有限公司共同发起&#xff0c; 由成都九天星空科技有限公司等联合打造的数字文创领域联盟链。平台采用FISCO BCOS 开源底层框架&#xff0c; 为数字文创产业构建一个高效、透明、可信的版权管理与交易平台。 平台专注于数字…...

# 使用自定义Shell脚本hello快速配置Linux用户账户

使用自定义Shell脚本快速配置Linux用户账户 在学校实验室管理Linux服务器&#xff0c;或者公司小团队管理服务器时&#xff0c;大家需要一个能隔离自己服务&#xff0c;但是自己又需要对服务器的完整权限的情形。创建和配置用户账户是一项常见但繁琐的任务。特别是当你需要频繁…...