工业网关 Quota 实战:从限流算法到分布式配额治理

5个4000比特大状态置换算法的设计与分析 下面是 5 个概念性、实验性的 4000 位可逆置换设计。它们都保证是双射,但未经过密码分析,不可直接用于生产系统。风格分别覆盖:三维 SPN、Feistel、可逆元胞自动机、ARX、宽轨迹/Keccak 式结构。 这 5 个设计分别代表了 SPN、Feistel、元胞自动机、ARX、宽轨迹 Keccak 五种不同风格,覆盖了主流大状态置换的构造思路。再次强调:它们只是实验性概念,若要用于实际协议,必须经过严格安全性分析。 阅读详情

工业网关通常不是单租户、单进程的简单程序:北向 API 会被多个应用调用,南向可能接入大量设备,本地还要承载数据缓存、历史导出、协议任务和云端上报。如果资源使用没有边界,一个异常应用、一个失控采集任务或一次历史导出,就可能挤占其他租户的连接、存储和上行带宽。

Quota 的价值不是简单“把请求拒绝掉”,而是把资源使用显式化:谁能用、能用多少、在什么周期内用、超出后走什么策略。本文从Zenova EdgeOS工程实战角度梳理工业网关中的配额类型、限流算法、Redis 原子实现、数据模型、降级策略和监测体系。

一、为什么工业网关需要 Quota

没有配额治理时,常见问题包括:

问题现场表现Quota 带来的约束
相互影响一个应用高频轮询,其他应用请求延迟上升按租户 / 应用限制 QPS
成本失控云端 API、上行流量、存储持续增长为流量和存储设置周期额度
资源不公平高频任务抢占连接、线程和 CPU为任务、连接和并发设置上限
故障定位难只知道网关慢,不知道谁在消耗资源配额维度天然提供用量画像
下游被打穿网关正常,但数据库或云 API 先过载让网关成为第一层背压点

配额设计的第一原则是:先定义保护对象,再定义限额。保护对象可以是网关自身,也可以是数据库、设备通道、云端 API、存储空间或上行带宽。

二、Quota 的核心类型

1. 速率配额

速率配额限制单位时间内的请求数、指令数或消息数,常见指标包括 QPS、RPS、每秒写入条数、每分钟调用次数。

适用场景:

  • 北向 OpenAPI 按租户限流;
  • 南侧采集任务限制扫描频率;
  • 云端上报限制批次速率;
  • 告警上报限制风暴扩散。

2. 容量配额

容量配额限制“最多有多少对象”,例如设备数、点位数、租户数、应用数、规则数、报表数。

容量配额通常是长周期或永久限制,适合控制授权边界和内存中的元数据规模。

3. 存储配额

存储配额限制磁盘空间、对象存储容量、历史数据保留量、日志保留量或数据库表大小。

工业现场尤其要注意:

  • 历史导出文件必须有配额和过期清理;
  • 日志、Trace、指标不能无限保留;
  • 离线缓存要设置上限和淘汰策略;
  • 磁盘使用率达到软阈值时必须先降级写入,而不是等磁盘满后整体故障。

4. 并发配额

并发配额限制同一时刻的连接数、任务数、线程数、设备会话数或慢查询数。

它和速率配额不同:速率关心“一段时间内来了多少”,并发关心“同一时刻占着多少”。例如 QPS 不高但每个请求耗时很长,仍可能耗尽连接池。

5. 流量配额

流量配额限制上行 / 下行字节数,常见于 4G / 5G 场景。可以按日 / 月设置总额度,也可以按消息类型设置优先级,例如控制指令和告警优先于历史数据补传。

三、配额维度设计

单维 Quota 很容易失效。工程上通常组合多个维度:

维度示例说明
租户tenant_id多租户 SaaS 或多项目隔离
应用app_id防止同一租户内应用互相影响
资源api.read、device.command、storage.local每类资源单独限额
实例gateway_id本地资源边界
周期秒、分钟、日、月突发控制和总量控制分别设计
优先级control、alarm、telemetry、export资源紧张时决定谁先被限制

推荐的最小键结构:

quota:{tenant_id}:{app_id}:{resource}:{period}

例如:

quota:tenant-a:scada:api.read:1m
quota:tenant-a:collector:device.command:1s
quota:tenant-a:edge:storage.local:total

不要把所有请求都塞进一个全局 key。全局 key 只能保护网关整体,不能提供租户间的公平性;只有租户 key 而没有全局 key,又可能在大量租户同时超限时打穿下游。

四、限流算法选型

1. 令牌桶:允许突发,控制平均速率

令牌桶按固定速率生成令牌,桶容量决定最大突发量。请求只有拿到令牌才允许通过。

import threading
import time


class TokenBucket:
    def __init__(self, rate: float, capacity: float):
        if rate <= 0 or capacity <= 0:
            raise ValueError("rate and capacity must be positive")

        self.rate = rate
        self.capacity = capacity
        self.tokens = capacity
        self.updated_at = time.monotonic()
        self.lock = threading.Lock()

    def acquire(self, tokens: float = 1.0) -> bool:
        if tokens <= 0 or tokens > self.capacity:
            raise ValueError("tokens must be in (0, capacity]")

        with self.lock:
            now = time.monotonic()
            elapsed = now - self.updated_at
            self.tokens = min(
                self.capacity,
                self.tokens + elapsed * self.rate,
            )
            self.updated_at = now

            if self.tokens < tokens:
                return False

            self.tokens -= tokens
            return True

适用场景:

  • 允许短时间内批量读取;
  • 控制平均上报速率;
  • 云端 API 有突发额度;
  • 下游能承受有限突发。

注意:这个实现只适合单进程。如果网关有多个 worker 或多实例,本地令牌桶会造成实际限流值为 单实例限额 × 实例数,需要 Redis 等中心化实现。

2. 漏桶:平滑输出,保护慢速下游

漏桶把不均匀的输入排队后按固定速率输出,适合保护处理能力稳定的下游。

import asyncio


class LeakyBucket:
    def __init__(self, rate: float, capacity: int):
        if rate <= 0 or capacity <= 0:
            raise ValueError("rate and capacity must be positive")

        self.queue: asyncio.Queue[None] = asyncio.Queue(maxsize=capacity)
        self.rate = rate
        self._task: asyncio.Task | None = None

    async def start(self) -> None:
        if self._task is None or self._task.done():
            self._task = asyncio.create_task(self._leak())

    async def stop(self) -> None:
        if self._task is not None:
            self._task.cancel()
            try:
                await self._task
            except asyncio.CancelledError:
                pass
            self._task = None

    async def acquire(self) -> None:
        if self._task is None:
            raise RuntimeError("bucket is not started")

        await self.queue.put(None)

    async def _leak(self) -> None:
        interval = 1.0 / self.rate
        while True:
            await asyncio.sleep(interval)
            try:
                self.queue.get_nowait()
                self.queue.task_done()
            except asyncio.QueueEmpty:
                pass

使用方式:

async def send_report(bucket: LeakyBucket, payload: dict):
    await bucket.acquire()
    await upload(payload)

适用场景:

  • 控制指令按固定速率下发;
  • 历史数据补传不抢占实时数据;
  • 下游协议栈处理速度稳定;
  • 允许请求排队而不是立即失败。

漏桶要显式设置队列上限、等待超时和取消策略,否则突发流量会把内存队列撑高,或者让请求等待过久。

3. 固定窗口:实现简单,但存在边界突刺

import time


class FixedWindow:
    def __init__(self, limit: int, window: float):
        self.limit = limit
        self.window = window
        self.count = 0
        self.window_start = time.monotonic()

    def acquire(self) -> bool:
        now = time.monotonic()
        if now - self.window_start >= self.window:
            self.count = 0
            self.window_start = now

        if self.count >= self.limit:
            return False

        self.count += 1
        return True

固定窗口的问题是边界效应:限制每分钟 600 次,前一个窗口最后 10 秒来 600 次,后一个窗口前 10 秒又来 600 次,则 20 秒内实际通过 1200 次。

因此固定窗口更适合粗粒度统计和低风险业务配额,不适合保护连接数敏感或容量敏感的下游。

4. 滑动窗口:更平滑,成本略高

滑动窗口只统计最近一个时间周期内的请求,可以消除固定窗口的边界突变。常见实现有:

  • Redis ZSET 保存窗口内唯一请求;
  • Redis INCR 分桶后加权统计;
  • 数据库按分钟聚合统计;
  • 本地环形队列。

其中 Redis ZSET 逻辑直观,但要注意成员唯一性、窗口清理和原子执行。

5. 并发配额:限制同时占用

import asyncio


class ConcurrencyLimiter:
    def __init__(self, limit: int):
        self.semaphore = asyncio.Semaphore(limit)
        self.active = 0

    async def __aenter__(self):
        await self.semaphore.acquire()
        self.active += 1
        return self

    async def __aexit__(self, exc_type, exc, tb):
        self.active -= 1
        self.semaphore.release()


async def read_device(limiter: ConcurrencyLimiter, device_id: str):
    async with limiter:
        return await query_device(device_id)

并发配额必须配置排队等待时间。否则请求虽然不会同时占用资源,但可能大量堆积在信号量队列中,最终表现为超时和内存增长。

算法选择表

算法优势代价适合场景
令牌桶平均速率稳定,允许可控突发需要处理桶容量和时钟API 调用、数据上报
漏桶输出平滑,保护慢速下游排队会引入延迟指令下发、历史补传
固定窗口实现和存储简单窗口边界可能双倍突发日配额、月配额
滑动窗口控制更精确存储和计算成本更高租户限流、公平调度
信号量限制同时占用需要超时和排队策略连接、任务、慢查询

五、Redis 分布式限流

多实例网关不能只依赖进程内计数。假设每个实例本地限制 100 QPS,部署 5 个实例后,全局可能达到 500 QPS。若要全局公平,需要中心化计数。

1. 原子滑动窗口 Lua 脚本

下面的脚本用 Redis 服务端时间避免多网关本机时钟不一致,用唯一请求 ID 作为 ZSET member,避免同一毫秒内的请求互相覆盖:

local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window_ms = tonumber(ARGV[2])
local request_id = ARGV[3]

local clock = redis.call('TIME')
local now_ms = clock[1] * 1000 + math.floor(clock[2] / 1000)
local cutoff_ms = now_ms - window_ms

redis.call('ZREMRANGEBYSCORE', key, '-inf', cutoff_ms)

local count = redis.call('ZCARD', key)
if count >= limit then
    redis.call('PEXPIRE', key, window_ms)
    return 0
end

redis.call('ZADD', key, now_ms, request_id)
redis.call('PEXPIRE', key, window_ms)
return 1

Python 调用示例:

import uuid


SLIDING_WINDOW_LUA = """
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window_ms = tonumber(ARGV[2])
local request_id = ARGV[3]

local clock = redis.call('TIME')
local now_ms = clock[1] * 1000 + math.floor(clock[2] / 1000)
local cutoff_ms = now_ms - window_ms

redis.call('ZREMRANGEBYSCORE', key, '-inf', cutoff_ms)

local count = redis.call('ZCARD', key)
if count >= limit then
    redis.call('PEXPIRE', key, window_ms)
    return 0
end

redis.call('ZADD', key, now_ms, request_id)
redis.call('PEXPIRE', key, window_ms)
return 1
"""


async def allow_request(
    redis,
    tenant_id: str,
    resource: str,
    limit: int,
    window_ms: int,
) -> bool:
    key = f"quota:{tenant_id}:{resource}:sliding"
    request_id = str(uuid.uuid4())

    allowed = await redis.eval(
        SLIDING_WINDOW_LUA,
        1,
        key,
        limit,
        window_ms,
        request_id,
    )
    return bool(allowed)

这里不能用普通 pipeline 替代 Lua:pipeline 只保证命令打包发送,不保证其他客户端不会在 ZCARD 和 ZADD 之间插入请求。分布式限流的核心是检查和写入必须原子执行。

原文示例里还有一个隐蔽问题:在 pipeline 中先执行 ZADD,再根据旧 count 判断是否允许。这会导致被拒绝的请求也被写入窗口,统计被拒绝流量污染。正确逻辑必须是“达到上限直接返回,未达到才写入”。

2. 固定窗口原子计数

日配额、月配额不需要滑动窗口,可以用 INCR:

local key = KEYS[1]
local limit = tonumber(ARGV[1])
local ttl_ms = tonumber(ARGV[2])

local current = redis.call('INCR', key)
if current == 1 then
    redis.call('PEXPIRE', key, ttl_ms)
end

if current > limit then
    return 0
end

return 1

适合月流量、日报表数、导出次数等粗粒度配额。若业务要求按自然日 / 自然月重置,TTL 应该设置为距离下一个重置点的时间,而不是固定 30 天。

3. Redis 故障时的策略

Quota 中心不可用时,不能只有一个“全部拒绝”或“全部放行”的答案,应按资源风险选择:

资源类型建议策略原因
控制指令本地保守限额后放行不能因限流中心故障阻断关键控制
实时告警放行并记录超额告警比精确限流更重要
历史数据补传延迟或降级可等待恢复
历史导出拒绝新任务避免存储和内存被占用
北向开放 API本地配额 + 短 TTL 缓存保持基本公平
第三方付费 APIfail-closed避免成本和配额失控

无论选择哪种策略,都必须暴露 quota_backend_error 指标,并在恢复后补齐审计记录。

六、配额数据模型

Redis 适合实时判断,数据库适合保存规则、审计和长期统计。不要只建一张 quotas 表,把规则和当前用量混在一起;否则并发更新和周期重置都容易产生竞态。

CREATE TABLE quota_rules (
    id BIGSERIAL PRIMARY KEY,
    tenant_id UUID NOT NULL,
    app_id VARCHAR(64) NOT NULL DEFAULT 'ALL',
    resource VARCHAR(128) NOT NULL,
    period VARCHAR(16) NOT NULL CHECK (period IN ('second', 'minute', 'hour', 'day', 'month', 'total')),
    quota_limit BIGINT NOT NULL CHECK (quota_limit > 0),
    burst_limit BIGINT,
    soft_threshold INTEGER CHECK (soft_threshold BETWEEN 1 AND 100),
    action VARCHAR(24) NOT NULL DEFAULT 'reject',
    enabled BOOLEAN NOT NULL DEFAULT TRUE,
    updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
    UNIQUE (tenant_id, app_id, resource, period)
);

CREATE TABLE quota_usage (
    tenant_id UUID NOT NULL,
    app_id VARCHAR(64) NOT NULL DEFAULT 'ALL',
    resource VARCHAR(128) NOT NULL,
    period VARCHAR(16) NOT NULL,
    period_start TIMESTAMP NOT NULL,
    used_amount BIGINT NOT NULL DEFAULT 0,
    rejected_count BIGINT NOT NULL DEFAULT 0,
    updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
    PRIMARY KEY (tenant_id, app_id, resource, period, period_start)
);

app_id 固定使用 ALL 表示租户级全局配额,避免 NULL 参与唯一键后出现多条同类规则。

规则变更要带版本号或更新时间。网关侧定期拉取规则,并在 Redis 故障时使用最近一次有效配置。

七、HTTP 入口集成

配额判断应该放在认证和授权之后,这样 key 才能绑定真实租户和应用,而不是匿名流量。

from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse


app = FastAPI()


@app.middleware("http")
async def quota_middleware(request: Request, call_next):
    tenant = request.headers.get("X-Tenant-ID")
    if not tenant:
        return JSONResponse(status_code=400, content={"message": "tenant is required"})

    allowed = await allow_request(
        redis=request.app.state.redis,
        tenant_id=tenant,
        resource="api.read",
        limit=600,
        window_ms=60_000,
    )
    if not allowed:
        raise HTTPException(
            status_code=429,
            detail="quota exceeded",
            headers={"Retry-After": "1"},
        )

    return await call_next(request)

接口返回时建议补充:

  • 429 Too Many Requests;
  • Retry-After,提示等待秒数;
  • 稳定的业务错误码,例如 QUOTA_EXCEEDED;
  • 响应头中的剩余额度和重置时间,必要时只暴露给内部调用方。

不要把 429 当成 500,也不要让客户端无限立即重试。SDK 应采用指数退避加抖动。

八、边缘场景的降级策略

工业边缘不能简单套用互联网 API 的“超限即拒绝”。不同数据的价值和时效完全不同。

数据 / 请求类型超限策略说明
控制指令预留额度,优先通过关键操作不应被历史数据挤占
实时告警放行、聚合、去重限流目标是防风暴,不是丢关键告警
实时遥测采样、聚合、降频可用聚合值替代原始高频点
历史补传排队、暂停、分时补传网络空闲时再执行
历史导出拒绝或排队防止磁盘、内存和 CPU 被长任务占用
第三方 API背压或降级缓存保护付费额度和外部依赖

一个实用的做法是预留额度:总配额的 80% 给普通流量,20% 保留给控制指令和告警。普通流量达到 80% 即触发降级,关键流量仍有一定余量。

九、配额观测与告警

Quota 上线后必须能看到“额度是否合理”,否则很容易从资源失控变成误伤业务。

1. 核心指标

指标说明
quota_used_ratio已用额度 / 总额度
quota_rejected_total被拒绝请求,按租户和资源聚合
quota_check_duration_seconds配额判断耗时
quota_backend_error_totalRedis / 数据库错误
quota_wait_duration_seconds排队类任务等待时间
quota_active_count当前并发占用

2. 告警建议

  • 使用率达到 80%:提示容量风险和规则评审;
  • 使用率达到 95%:准备降级或扩容;
  • 拒绝率突增:判断是异常调用、业务增长还是配额过小;
  • Redis 错误率上升:确认故障策略生效;
  • 配额判断 P99 延迟过高:限流组件正在拖慢主链路;
  • 单租户持续接近上限:评估是否调整套餐或隔离热点。

3. 审计事件

关键动作要记录:

  • 配额规则创建、修改、禁用;
  • 配额被触发时的动作;
  • 降级策略切换;
  • 手动放行或临时扩额;
  • 周期重置。

审计日志建议包含 tenant_id、app_id、resource、quota_limit、used、action、request_id 和操作者。

十、工程实践清单

  1. 按保护对象设计配额,而不是只按接口路径限制;
  2. 速率、容量、存储、并发、流量分别建模;
  3. 令牌桶允许突发,漏桶平滑输出,固定窗口注意边界突刺;
  4. 多实例场景使用 Redis Lua 保证检查和写入原子;
  5. Redis ZSET 使用唯一 request ID,避免同毫秒请求覆盖;
  6. 规则存数据库,实时判断走 Redis,网关本地保留最近有效配置;
  7. 为控制指令和告警预留额度;
  8. 为历史补传、导出、报表等低优先级任务设计排队和暂停策略;
  9. 429 响应携带稳定错误码和 Retry-After;
  10. 监控使用率、拒绝率、后端错误率和判断延迟;
  11. 配额规则变更进入审计日志;
  12. 定期回顾误伤率和资源利用率,避免拍脑袋限额。

十一、常见坑与应对

常见坑现象应对
本地限流当全局限流实例越多,实际限额越大Redis 或中心服务统一判断
检查和写入不原子并发下超额通过Lua、事务或数据库原子更新
被拒绝请求也计数拒绝流量污染配额窗口只把成功占用的请求写入使用量
ZSET member 用时间戳同一秒请求互相覆盖使用 UUID 或请求 ID
忽略窗口边界固定窗口边界突发翻倍使用滑动窗口或分桶加权
只有硬限制一个导出任务导致关键数据被拒软阈值 + 优先级 + 预留额度
队列无上限请求延迟和内存持续增长设置排队上限、等待超时和取消
Redis 故障无预案全部放行或全部拒绝按资源风险选择降级策略
无观测不知道限额是否合理使用率、拒绝率、错误率、延迟
规则不可追溯临时调额无审计规则版本化和审计事件

十二、TL;DR

  • Quota 是资源治理机制,不只是接口限流;
  • 类型包括速率、容量、存储、并发和流量;
  • 令牌桶适合可控突发,漏桶适合平滑输出,滑动窗口适合精确公平限流;
  • 多实例必须中心化,Redis 检查和写入要用 Lua 原子执行;
  • 数据库保存规则与审计,Redis 保存实时窗口;
  • 工业边缘要按业务优先级降级,为控制指令和告警预留额度;
  • 所有配额都要接观测,否则无法判断是保护系统还是误伤业务。

下一步建议

  1. 盘点网关的北向 API、南向设备任务、存储和上行流量保护对象;
  2. 设计租户、应用、资源、周期和优先级维度;
  3. 选择令牌桶、漏桶或滑动窗口,并明确突发与排队策略;
  4. 实现 Redis 原子限流和本地故障降级;
  5. 建立配额规则表、审计事件和使用率监控。
如何制作poster以及下载poster模板 目录 前言 一、poster 二、制作软件 1.常用软件 2.专用工具 3.模板下载网址 总结 前言 随着会议的发展,参与国际会议成为研究工作展示的重要途径。poster逐步成为一个方面专家交流的重要工具。本文主要简单介绍一些poster的制作工具。 一、poster Paper, presentation, poster是deadline期间作者的三座大山。poster的内容较小,但内容都是论文中的干货。 二、制作软件 一般来说,制作poster使用PowerPoint. 阅读详情

相关推荐

基于Opencv+Mediapipe的头部姿态检测

在学生课堂专注度检测项目中,可以通过学生头部姿态来确定学生注意力方向,从而判断其是否专注于课堂。

weixin_67879842的博客 2335

算法日常・每日刷题--<动态规划>42

本题为“不相交的线”,与最长公共子序列问题相似。使用动态规划求解:定义 dp[i][j] 表示 nums1[0:i] 与 nums2[0:j] 的最大不相交连线数。若元素相等,则继承左上值加1;否则取上方或左方最大值。最终返回 dp[m][n],即两数组的最大不相交连线数。时间复杂度 O(mn),空间复杂度 O(mn)。

2503_92261635的博客 12

LSTM量化选股实战:从数据清洗到回测归因的工程化闭环

LSTM(长短期记忆网络)是一种专为建模长程依赖而设计的循环神经网络,其门控机制能有效应对金融时序数据的非线性、高噪声与动态演化特性。相比传统统计模型或简单RNN,LSTM在股价趋势建模中展现出更强的鲁棒性与泛化能力,尤其适合处理日频多因子时序信号。其技术价值不仅在于提升预测精度,更在于支撑可归因、可审计的量化策略工程实践——从特征构建、标签定义到滚动回测,每一步都需严防未来信息泄露与过拟合风险。典型应用场景包括A股多因子选股、行业轮动信号生成及Alpha组合优化。本文聚焦LSTM在真实量化场景中的落地难点

weixin_33158887的博客 397

C语言程序设计题|有序数组插入数字冒泡排序

题目要求将一个数插入有序数组末尾,并用冒泡排序实现整体升序。代码先将输入数存入数组最后位置,再通过双重循环进行冒泡排序,每轮将较大元素向后移动,最终输出11个升序元素。该方法虽时间复杂度为O(n²),但符合题目要求,逻辑清晰,适合初学者理解排序原理。

2301_81429079的博客 436

OrthoFinder功能、流程和文件注释

OrthoFinder 的标准输出包括:直系同源组,直系同源基因,有根基因树,解析基因树,无根物种树、有根物种树,基因重复事件以及相关的统计数据。

hs6605015的博客 3045

LVGL 离线字体转换lv_font_conv本地安装

LVGL FONT CONV 离线版本

liu132641的专栏 3381

【算法拾光】模拟|外观数列 + 数青蛙

本文总结两道模拟题解法:外观数列通过迭代统计连续数字个数生成下一项,关键在于处理末尾字符;数青蛙则模拟青蛙叫声“croak”状态转移,维护各阶段青蛙数量,记录最大并发数并确保全部完成。共性在于严格遵循流程、细致处理边界与非法情况,锻炼字符串遍历与状态管理能力。

wuqingyigexiaoba的博客 359

医学图像分割实战:基于TransUNet训练自己的眼底硬渗出物数据集(附完整代码)

本文详细介绍了基于TransUNet的眼底硬渗出物分割实战指南,涵盖数据预处理、模型调优、训练策略及性能优化等关键环节。通过代码复现和实验对比,展示了TransUNet在医学图像分割中的优势,为糖尿病视网膜病变的早期诊断提供技术支持。

weixin_42524708的博客 361

【数据结构-3】算法美学之降复杂度

在while循环的循环体内,首先用临时变量保存最后一个位置的数据,再通过for循环把所有元素往后移动一位,最后把tmp中保存的值放到下标为0的位置上去。方法二的思路是:创建新数组,让原数组中后k个数据移动到新数组中前面的位置,让原数组中前numsSize-k个数据移动到新数组中后面的位置,这。这段代码的思路是:三次逆置,第一次逆置前numsSize-k个数据,第二次逆置后k个数据,最后整体逆置。这篇博文分享一道解法不一的算法题,求解过程的目的在于降低算法的时间复杂度,题源力扣。,属于空间换时间的操作。

weixin_44218929的博客 76

理想汽车智驾方案介绍 4 World model + 强化学习重建自动驾驶交互环境

本帖将以 DrivingSphere 为例来解析这个过程。

地平线开发者 1920

【PLC】三菱plc控件安装 component Movedata had the following error ... Error Number:-119

Windows 10 专业版/企业版本版本号:22H2操作系统内部版本:19045.3448。

少莫千华 8000

AI和大模型—从克里金算法说开去

克里金算法源于矿业勘探,通过空间自相关性实现稀疏数据下的最优预测,核心优势在于不确定性量化。在AI大模型中,其等价于高斯过程,广泛应用于超参数优化、小样本建模与推理调度。尽管面临计算复杂度高、核函数选择难等问题,通过稀疏化、分治法与低秩近似可有效优化。该方法在降低训练成本、提升泛化能力及减少幻觉方面表现突出,尤其适用于高维、高成本的智能系统优化,具有重要借鉴价值。

fpcc的专栏 601

Amesim与Simulink联合仿真:S-Function接口配置与实战避坑指南

本文详细介绍了Amesim与Simulink联合仿真中S-Function接口的配置方法与实战避坑指南。从环境搭建、编译器配置到S-Function接口实战,逐步解析关键步骤与常见问题解决方案,帮助工程师高效实现多领域系统仿真,特别适合汽车、航空航天等复杂系统建模场景。

weixin_29173777的博客 343

算法日常・每日刷题--<动态规划>32

给定严格递增的正整数数组,求最长斐波那契子序列长度。使用二维DP,dp[i][j]表示以arr[i]、arr[j]为最后两项的序列长度,初始化均为2。通过哈希表快速查找前一项target = arr[j] - arr[i],若存在且下标小于i,则状态转移:dp[i][j] = dp[k][i] + 1。遍历更新全局最大长度,最终若结果小于3则返回0。时间复杂度O(n²),空间复杂度O(n²)。

2503_92261635的博客 174

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

算法札记:几何分布在算法题UVA1262的运用

集卡问题求解核心:将集齐n种优惠券的过程分为n个阶段,每个阶段期望购买次数为 $ \frac{n}{k} $(k为剩余种类数),总期望为 $ n \cdot H_n $(调和数)。通过自洽方程推导单阶段期望,无需几何分布或无穷级数,逻辑清晰且适用于大一水平。例如,n=5时期望约11.42,非5。题目要求以带分数形式输出精确结果,算法上需累加分数并化简。

Keven_11的博客 300

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

不同的二叉搜索树

互不相同的二叉搜索树的种数,以 j (1<=j<=i)为头节点,左子树是 j-1 个数,右子树就是 i - (j - 1) -1 = i - j个数。所以dp[3] = dp[0] * dp[2] + dp[1] * dp[1] + dp[2] * dp[0]头1 = 左子树0节点 * 右子树2节点,二叉搜索树就是排序树,左子树<根节点<右子树,左右子树也满足左子树<根节点<右子树。头2 = 左子树1节点 * 右子树1节点。所以dp[i] += dp[j-1] * dp[i-j]个节点组成且节点值从。

qq_44721738的博客 150

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

固件开发岗算法

背景:嵌入式固件岗,偏爱手写库函数、位运算、数组基础算法。

2502_90352018的博客 108

SSL证书选RSA还是ECDSA:公钥算法、CA签名与兼容性怎么核对

申请SSL证书时,RSA和ECDSA该怎么选?先分清站点公钥算法、CA签名算法和TLS实际兼容性,再用隔离OpenSSL实验读取两类材料,核对申请、续期和部署交接,避免只看Signature Algorithm就选错。

谁呀!的博客 375

从曲线到储层:Techlog/KAPPA 全流程算法、UltraLAB 选型与本地 AI 部署实战

以高频 CPU 保证交互,以充足内存承载多井与多任务,以 NVMe 打通项目和知识库 I/O,再按本地模型、上下文与并发配置 GPU。对 UltraLAB 用户而言,更合理的采购方式是带着真实项目做选型:一组典型井、一套完整解释模板、一个目标大模型、一次多人并发测试。用实测结果确定配置,才能把预算转化为解释效率,而不是闲置算力。软件模块、操作系统与许可条件以厂商当前正式说明为准;硬件建议需结合项目实测。AI 输出只能作为辅助证据,不能替代岩石物理与油藏工程专业审核。

wdf8088的博客 158

【Deep-OC-SORT 01】多轨迹算法Deep-OC-SORT源码分析

本工程基于Deep-OC-SORT核心模块,重构并适配了EmbeddingComputer(外观特征提取)、CMCComputer(相机运动补偿)与OCSort(主跟踪器)三类。前者实现整框/网格模式的特征提取与L2归一化;后者通过稀疏光流或SIFT匹配估计仿射变换,补偿相机运动;主跟踪器融合IoU、外观相似度与方向一致性,支持模块开关与自定义组件,实现高效多目标跟踪。

Jayson 博客 330

C++ 标准库算法全景指南

本文系统梳理C++标准库<algorithm>与<numeric>中100+算法,按功能分为非修改、修改、排序、二分查找、归并、堆、极值、字典序、排列及数值操作十大类,涵盖典型用法与时间复杂度。结合C++20范围(ranges)与投影特性,实现更简洁高效的代码。

sss123ddd的博客 211

高速公路无人机巡检系统:场景、算法与部署方案

高速公路巡检的工程矛盾,不在“能不能飞到”,而在“端侧算力、时延约束与精度要求三者之间如何分配”。路面病害要求毫米级识别,但高速动态成像与运动模糊压制了单帧精度;交通事件要求秒级推送,但隧道与峡谷的通信盲区切断了云端链路;桥梁梁底的无卫星信号环境,则把自主定位的难度推到了GNSS失效的边界。本文从“端—边—云”三级协同的工程逻辑出发,拆解路面病害、交通事件、桥梁结构三类场景下算法与部署的实际取舍,结合重庆绕城高速、广西六宾高速、南京6G低空巡检等公开数据,给出可复用的系统设计参考。

THJS优快云的博客 185

算法日常・每日刷题--<动态规划>41

给定两个字符串text1和text2,求其最长公共子序列长度。使用动态规划,定义dp[i][j]为text1前i个字符与text2前j个字符的最长公共子序列长度。若字符相等,则dp[i][j] = dp[i-1][j-1] + 1;否则取舍弃一方的最大值:dp[i][j] = max(dp[i-1][j], dp[i][j-1])。最终返回dp[m][n]。时间复杂度O(mn),空间复杂度O(mn)。

2503_92261635的博客 115

Consistent-Point半监督人群计数算法详解

本文首次指出并量化了点定位半监督人群计数中伪点的位置不一致与类别不一致问题(Mean-Teacher baseline 甚至不如只用标注数据),并给出两个极简正交模块——PA 用"被匹配的伪点与其邻近提议点定位相似"的洞察做空间平均,以 1/K 方差收缩稳住位置;IUC 用分类得分做实例级加权,压低决策边界附近模糊伪点的监督强度。两模块零推理开销、只引入一个超参 λ,在 5 数据集 × 3 标注比例的 15 个定位设置上全部 SOTA,并在 CPS 框架上验证泛化性,说明"伪标签一致性"是点定位半监督范式中

Keep_Trying_Go的博客 319

嵌入式 AI 智能相机怎么选?从算力、算法架构、部署方式深度对比

在工业自动化视觉检测场景中,嵌入式 AI 智能相机正在逐步替代传统 “工业相机 + 上位机工控机” 的方案。但市面上产品参数繁杂,很多工程师选型时容易被纸面算力、宣传卖点误导。本文从**持续算力性能、算法架构设计、现场部署模式**三个核心维度,梳理嵌入式视觉设备不同技术路线的差异、适用边界与落地痛点,为机器视觉工程师、自动化集成商、产线技改负责人提供可落地的选型参考。

VisionDataLab的博客 289

算法1. 双指针法-移动零

【代码】算法1. 双指针法-移动零。

2603_95728536的博客 228
上一篇: Go 工业边缘错误处理实战:用 errors 构建可追溯错误链
下一篇: 工业网关 Quota 实战:从限流算法到分布式配额治理
Zenova EdgeOS
博客等级 码龄140天 44粉丝 190原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值