学习LRUs @-}当超能力使你的系统变得更好时 (中文 (Chinese Simplified))

学习LRUs @-}当超能力使你的系统变得更好时

Tuesday, 09 December 2025

//

12 minute read

多数系统在超载后会退化@. @ memorys fill up,}查询慢下来 @,}用户抱怨#,}服务器崩溃=.}

几个不同寻常的 更好.

本条说明: 基于 LRU 的行为内存 当它触动到能力时, 自我=-\优化 =\ - 和这种模式如何驱动我的学习系统 机器人检测引擎. 这也是尽可能最小的版本 DISE 建筑结构 -通过资源压力控制进化

如果你读了我的文章 CQRS 和事件检验您的, @ '}会认出这里的一些模式@. @ 但是这是 CQRS 被剥除到骨骼上的 CQERS {-}\ n无事件商店 沒有預測,}沒有 Marten}.} 只是一個記憶缓存_, 背景工人,}和 SQLite+.}

预算基本行为记忆

在我们潜水前 请让我定义一个术语 I' 会在整个:中使用 签名. 签名是代表一种行为模式的任何稳定键@- a hash of IP IP @+%-Agenti,}标题组合的指纹{, 检测器MS K6ZMK7此请求看起来像 X". 缓存存储这些签名以及随着时间推移而演变的学习重量.}

如果你能建立一个 能够建立:的系统

  • 在“1”%s下响应
  • 从不在数据库中填入区块
  • 压力下的自定义@- @opptimis
  • 忘记什么并不重要
  • 记得什么是

这到底是什么? IMemoryCache 滑动到期后, 如果您了解您正在建造的“ '” 是什么的话, 您将获得 MPK0 @ label

什么是路透缓存实际上

LRU ( @Lestern 最近使用过的)}缓存将最近访问到的条目驱逐@'}当缓存填满了,}最冷的条目被扔出去,让它们能容纳热的条目_.}*

多数开发商认为这是一个限制@. @% @ "Oh no,我的缓存已满 , 数据正在丢失!"

但对于行为系统来说 , 这是个特写

// From WeightStore.cs - the bounded memory window
_cache = new MemoryCache(new MemoryCacheOptions
{
    SizeLimit = _cacheSize,           // e.g., 1000 entries
    CompactionPercentage = 0.25       // Remove 25% when limit reached
});

这: SizeLimit 不只是一个内存限制@ . @ it'}a 选项选择压力@. 它决定了系统 $#"}{"}和迫使它关注什么重要事 □.}

滑动过期@ - @ 忘记的时钟

加上滑动过期@,}您会自动忘记 @:

// From WeightStore.cs:254-259
private MemoryCacheEntryOptions GetCacheEntryOptions()
{
    return new MemoryCacheEntryOptions()
        .SetSlidingExpiration(_slidingExpiration)  // 30 minutes
        .SetSize(1);  // Each entry counts as 1 toward size limit
}

如果签名在 @30 minutes@,}(分钟 1) 内访问到的签名是“'Qt ” ,那么它会驱逐{'不是因为它<'> 错误了-} 因为它#'{不再相关 *_.}

由此创建 自然遗忘:

  • 实施伙伴被重新分配
  • Bot 旋转签名
  • 交通模式转变
  • 昨天的'攻击是今天的'

静态区块列表会变平@ . @ 滑动过期, 让内存保持清新Q.@

ImemoryCache 模式@ - 微小 CQRS 不说 CQRS

这里“'}这是它赖以运作的模式 ” @. SqliteWeightStore 类别 @: @%

/// <summary>
///     SQLite implementation of the weight store with sliding expiration memory cache.
///     Uses a CQRS-style pattern with write-behind:
///     - Reads: Hit memory cache first (fast path), fall back to SQLite on miss
///     - Writes: Update cache immediately, queue SQLite writes for background flush
///     Sliding expiration provides automatic LRU-like eviction behavior.
/// </summary>

public class SqliteWeightStore : IWeightStore, IAsyncDisposable
{
    // Memory cache with sliding expiration - auto-evicts least recently used entries
    private readonly MemoryCache _cache;

    // Write-behind queue for batched SQLite persistence
    private readonly ConcurrentDictionary<string, PendingWrite> _pendingWrites = new();
    private readonly Timer _flushTimer;
    private readonly TimeSpan _flushInterval = TimeSpan.FromMilliseconds(500);

这是 非正式的CQRS {-}但若无乏味的缓存失效>.} 而不是在写<,}后取消缓存条目。 缓存是写模型.SQLite只是永久的分类账

flowchart LR
    subgraph Cache["In-Memory Behaviour Store"]
        A[Hot Signatures] --- B[Sliding Expiry]
    end
    subgraph DB["SQLite Ledger"]
        C[(Durable Write-Behind)]
    end

    A --Periodic Flush--> C
    B --Eviction--> D[Forgotten]

    style Cache fill:none,stroke:#10b981,stroke-width:2px
    style DB fill:none,stroke:#6366f1,stroke-width:2px

关键洞察力: 读写到内存数据库最终是一致的 -和'都很好

总是读取路径@ - @ 缓存 first @ MS K1}

当检测器需要学习重量时\ ,}它会击中缓存@:

// From WeightStore.cs:421-472
public async Task<double> GetWeightAsync(
    string signatureType,
    string signature,
    CancellationToken ct = default)
{
    var key = CacheKey(signatureType, signature);

    // Check cache first (fast path - no DB access)
    if (_cache.TryGetValue(key, out LearnedWeight? cached) && cached != null)
    {
        _metrics?.RecordCacheHit(signatureType);
        return cached.Weight * cached.Confidence;
    }

    _metrics?.RecordCacheMiss(signatureType);

    // Cache miss - load from DB
    await EnsureInitializedAsync(ct);

    await using var conn = new SqliteConnection(_connectionString);
    await conn.OpenAsync(ct);

    var sql = $@"
        SELECT weight, confidence, observation_count, first_seen, last_seen
        FROM {TableName}
        WHERE signature_type = @type AND signature = @sig
    ";

    // ... execute query ...

    if (await reader.ReadAsync(ct))
    {
        // Cache the result for future reads
        var learnedWeight = new LearnedWeight { /* ... */ };
        _cache.Set(key, learnedWeight, GetCacheEntryOptions());

        return weight * confidence;
    }

    return 0.0;  // No learned weight exists
}

热路 从未访问过数据库SQLite只是备份存储@. @

写入路径@ - @ 缓存立即,+Persist 稍后

当系统学习一些新@ ,} 它会立即更新缓存并排队数据库写入\ MS K1}

// From WeightStore.cs:551-582
public Task UpdateWeightAsync(
    string signatureType,
    string signature,
    double weight,
    double confidence,
    int observationCount,
    CancellationToken ct = default)
{
    var key = CacheKey(signatureType, signature);

    // Update cache immediately (source of truth for reads)
    var learnedWeight = new LearnedWeight
    {
        SignatureType = signatureType,
        Signature = signature,
        Weight = weight,
        Confidence = confidence,
        ObservationCount = observationCount,
        FirstSeen = DateTimeOffset.UtcNow,
        LastSeen = DateTimeOffset.UtcNow
    };
    _cache.Set(key, learnedWeight, GetCacheEntryOptions());

    // Queue for async SQLite persistence (write-behind)
    QueueWrite(signatureType, signature, weight, confidence, observationCount);

    return Task.CompletedTask;
}

通知@: UpdateWeightAsync 返回返回 Task.CompletedTask @ - @ it'} 基本上同步@ MS K2 @ 书写是队列的\ , @ 未执行 @ I. @ 这意味着@ MPK5 @

  • Sub-milli 秒写缓存
  • 在 I/O 上没有屏蔽
  • 写作是联合的 @(#最后一次写入 wins@)}%

背景 Flusher @ - @ @ I500#% 无聊魔术的背景

@500@ms@,}每封未写的文章都会被冲到 SQLite 上,

// From WeightStore.cs:274-357
public async Task FlushPendingWritesAsync(CancellationToken ct = default)
{
    if (_pendingWrites.IsEmpty) return;

    // Only one flush at a time
    if (!await _flushLock.WaitAsync(0, ct)) return;

    try
    {
        await EnsureInitializedAsync(ct);

        // Snapshot and clear pending writes atomically
        var writes = new List<PendingWrite>();
        foreach (var key in _pendingWrites.Keys.ToList())
        {
            if (_pendingWrites.TryRemove(key, out var write))
            {
                writes.Add(write);
            }
        }

        if (writes.Count == 0) return;

        await using var conn = new SqliteConnection(_connectionString);
        await conn.OpenAsync(ct);
        await using var transaction = await conn.BeginTransactionAsync(ct);

        try
        {
            var sql = $@"
                INSERT INTO {TableName}
                    (signature_type, signature, weight, confidence,
                     observation_count, first_seen, last_seen)
                VALUES (@type, @sig, @weight, @conf, @count, @now, @now)
                ON CONFLICT(signature_type, signature) DO UPDATE SET
                    weight = @weight,
                    confidence = @conf,
                    observation_count = @count,
                    last_seen = @now
            ";

            foreach (var write in writes)
            {
                await using var cmd = new SqliteCommand(sql, conn, transaction);
                // ... add parameters and execute ...
            }

            await transaction.CommitAsync(ct);
            _logger.LogDebug("Flushed {Count} pending writes in {Duration:F1}ms",
                writes.Count, sw.ElapsedMilliseconds);
        }
        catch
        {
            await transaction.RollbackAsync(ct);
            throw;
        }
    }
    finally
    {
        _flushLock.Release();
    }
}

这是 事件@-_group @-}光MSKO你得到的:

  • Batched 寫作 @(#appactive I/_O)}
  • 交易一致性
  • 如果相同的签名在 @500}%s@ms=,}中更新了 10次,则仅写入最终值@)}
  • SQLite 对这种访问模式非常满意

EMA 更新 -学习指数移动平均值

当新观测到达时, 系统使用指数移动平均值来更新重量@:}

// From WeightStore.cs:584-635
public Task RecordObservationAsync(
    string signatureType,
    string signature,
    bool wasBot,
    double detectionConfidence,
    CancellationToken ct = default)
{
    var key = CacheKey(signatureType, signature);

    // Calculate new weight using EMA in memory
    var alpha = 0.1;  // Learning rate
    var weightDelta = wasBot ? detectionConfidence : -detectionConfidence;

    double newWeight;
    double newConfidence;
    int newObservationCount;

    if (_cache.TryGetValue(key, out LearnedWeight? existing) && existing != null)
    {
        // Apply EMA: new_weight = old_weight * (1-α) + delta * α
        newWeight = existing.Weight * (1 - alpha) + weightDelta * alpha;
        newConfidence = Math.Min(1.0, existing.Confidence + detectionConfidence * 0.01);
        newObservationCount = existing.ObservationCount + 1;
    }
    else
    {
        // First observation
        newWeight = weightDelta;
        newConfidence = detectionConfidence;
        newObservationCount = 1;
    }

    // Update cache immediately
    var learnedWeight = new LearnedWeight
    {
        SignatureType = signatureType,
        Signature = signature,
        Weight = newWeight,
        Confidence = newConfidence,
        ObservationCount = newObservationCount,
        FirstSeen = existing?.FirstSeen ?? DateTimeOffset.UtcNow,
        LastSeen = DateTimeOffset.UtcNow
    };
    _cache.Set(key, learnedWeight, GetCacheEntryOptions());

    // Queue for persistence
    QueueWrite(signatureType, signature, newWeight, newConfidence, newObservationCount);

    return Task.CompletedTask;
}

EMA 公式平滑学习@: @% new_weight = old_weight × (1 - α) + new_value × α

带着=和0.1:

  • 新证据提供#10%
  • 历史证据提供#90%
  • 这防止了一次观测的野生波动

为什么超支使系统成为系统 更好

这里的'是大多数人怀念 .的关键见解

当缓存填充:时

  • 低端-}频率信号掉出
  • 只有热的 @ ( @ 经常访问@ MS K1 @ 签名留在记忆中
  • 数据库的时差以一个电流循环@ - @ 和该+'}%s fine
  • 系统 焦点集中 压力下

想想看,如果“50,000”独有的签名击中了您的机器人探测器@,}但您只有对“MS K3”的内存。

最热门的10,000 通常代表实际交通量的99%

在制作《,》中,我看到大约每天 . 1-off 签名 “(crappers 尝试一次“,随机探查”\MS K5 合法用户,他们再也不会回来") 和也许5–10,000 不断回覆的<.}这些#5–10,000是风险生命中的“99%MSK11k12tail sign@?noiseMSQZ14t 伤害检测精度 {'}它甚至会通过减少低-信任模式的假阳性来改善它

flowchart TB
    subgraph Input["50,000 Unique Signatures"]
        Hot[Hot Signatures\n~10,000]
        Cold[Cold Signatures\n~40,000]
    end

    subgraph Cache["Bounded Cache (10,000)"]
        Kept[Kept in Memory]
    end

    subgraph Evicted["Evicted"]
        Lost[Forgotten\nNoise Traffic]
    end

    Hot --> Kept
    Cold --> Lost

    style Hot fill:none,stroke:#10b981,stroke-width:2px
    style Cold fill:none,stroke:#94a3b8,stroke-width:2px
    style Kept fill:none,stroke:#10b981,stroke-width:2px
    style Lost fill:none,stroke:#ef4444,stroke-width:2px

溢流 锐利 行为内存@. @ 系统自定义 @ - @ optiminises. @

当溢出时

这是't magic}. 有一些边缘案例 LRU的压力对你起作用

  • 缓存太小了: 如果您的缓存只持有 @100条目,但您有真正重要的签名@1,000}{,} 您在积累足够证据前会不停地发作并失去有用的模式\□'ll}

  • 统一运输: 如果您在微小的内部系统中运行, 其中几乎一切都是 @"Hot" (ffew 独有的签名 @MS K5}所有重复的), 溢出都使您的收益更少 @.}选择压力对“.”无可选择

  • Cold- 启动问题最新部署的系统没有学习到重量 所有东西都同样寒冷 在热点信号建立之前 前几小时会有更高的假正率

该模式在您拥有时最有效 具有功率的高度基点@- @Law 分布 “-”很多独特的签名“,” 但是一个小子集 控制着交通量“MS K2” 那“MSC3”和“机器人检测流量”完全一样

将缓存和数据库保存在同步的 - Tag\ I- 基于无效

缓存是读取的真理源@,}但数据库是持久的分类账 @.}当它们漂移时会怎样?

衰减的同步同步化

当数据库重量衰减\ ,时,缓存需要跟随\ MPK1 DecayOldWeightsAsync 使用两种方法处理 :\

// From WeightStore.cs:725-766
public async Task DecayOldWeightsAsync(TimeSpan maxAge, double decayFactor, CancellationToken ct = default)
{
    await EnsureInitializedAsync(ct);

    await using var conn = new SqliteConnection(_connectionString);
    await conn.OpenAsync(ct);

    var cutoff = DateTimeOffset.UtcNow.Subtract(maxAge).ToString("O");

    // Decay old weights in the database
    var sql = $@"
        UPDATE {TableName}
        SET weight = weight * @decay,
            confidence = confidence * @decay
        WHERE last_seen < @cutoff
    ";

    await using var cmd = new SqliteCommand(sql, conn);
    cmd.Parameters.AddWithValue("@decay", decayFactor);
    cmd.Parameters.AddWithValue("@cutoff", cutoff);

    var updated = await cmd.ExecuteNonQueryAsync(ct);

    // Delete weights that have decayed below threshold
    var deleteSql = $@"
        DELETE FROM {TableName}
        WHERE confidence < 0.01 OR (ABS(weight) < 0.01 AND observation_count < 5)
    ";

    await using var deleteCmd = new SqliteCommand(deleteSql, conn);
    var deleted = await deleteCmd.ExecuteNonQueryAsync(ct);

    if (updated > 0 || deleted > 0)
    {
        _logger.LogInformation(
            "Weight decay: {Updated} decayed, {Deleted} deleted",
            updated, deleted);

        // Compact cache to remove stale entries
        _cache.Compact(0.25);
    }
}

数据库记录衰减后 @, @ we call _cache.Compact(0.25) -这迫使 MemoryCache 将最近使用过的“.”优先排序。 下一读将会从数据库中重新装入新值@.}

Tag-基于驱逐

有时您需要取消整个类缓存条目 {-} 的无效性, 例如当再培训检测器时或当外部数据更改时\ :} 。

// From WeightStore.cs:768-777
/// <summary>
///     Evicts all cached entries for a specific signature type (tag-based eviction).
/// </summary>

public void EvictByTag(string signatureType)
{
    // MemoryCache doesn't natively support tag-based eviction, but we can compact
    // For now, just compact - sliding expiration will handle stale entries
    _cache.Compact(0.1);
    _logger.LogDebug("Compacted cache for signature type: {SignatureType}", signatureType);
}

.NET @NSK1%s# MemoryCache : 强制退出 stale 条目@, 让我们从数据库中读取重新聚集Q.

同步战略

关键的观点是 完全同步是有必要的系统容忍漂移,因为... ...:...

  1. DB 的缓存遗漏未重装入 - 如果条目被驱逐@, 下一读取新数据
  2. 滑动过期处理柄的渐变 @ - @ {% 1} 未进入的条目@ MS K1 @ minutes auto @ MPK2 @ evict
  3. 装甲部队的更新 - 定期压缩推出旧条目
  4. 在联合后写-}更新 @-多个快速更新变成 DB 写入

这是最终完成的一致 右@. @% 此缓存会停留在数据库中, 而无需复杂的无效逻辑@ . @ @ action

flowchart TB
    subgraph Sync["Cache-Database Synchronisation"]
        D[Database Decay] --> C[Cache Compact]
        E[Tag Eviction] --> C
        S[Sliding Expiration] --> M[Cache Miss]
        M --> R[Reload from DB]
    end

    style Sync fill:none,stroke:#6366f1,stroke-width:2px

没有缓存无效性地狱@ . @ 无复式酒吧@ MPK1_ sub @ MS K2} Just clatication and 自然过期@ I.

正在深解@ : @ 声望系统

注:: 如果您想要 LRU @+}写下「 -} 后面的樣式」 < ,> 您可以在此停止此處 < MS K3} 這篇文章其他部分顯示我如何對全套名譽 {- – 州機}, – 歇斯底里\ , 和時代衰變♪.@ MSKO8_ 用于這些建構應變系統 < I. >

歇歇和衰变

对于典型的名声 ( 跟踪签名是机器人还是人,随时间推移 □), 同样的原则适用,但具有更多精密性 :

// From PatternReputation.cs:42-108
public record PatternReputation
{
    public required string PatternId { get; init; }
    public required string PatternType { get; init; }
    public required string Pattern { get; init; }

    /// <summary>Current bot probability [0,1]. 0 = human, 1 = bot, 0.5 = neutral</summary>

    public double BotScore { get; init; } = 0.5;

    /// <summary>Effective sample count - decays over time, increases with observations</summary>

    public double Support { get; init; } = 0;

    /// <summary>Current reputation state - determines fast-path behavior</summary>

    public ReputationState State { get; init; } = ReputationState.Neutral;

    // Computed properties
    public double Confidence => Math.Min(1.0, Support / 100.0);

    public bool CanTriggerFastAbort =>
        State is ReputationState.ConfirmedBad or ReputationState.ManuallyBlocked;

    public bool CanTriggerFastAllow =>
        State is ReputationState.ConfirmedGood or ReputationState.ManuallyAllowed;
}

具有歇斯底西氏症的州过渡

模式从中立直接翻转到确认的Bad.

// From PatternReputation.cs:367-421 - simplified
public PatternReputation EvaluateStateChange(PatternReputation reputation)
{
    if (reputation.IsManual)
        return reputation;

    var newState = reputation.State;
    var score = reputation.BotScore;
    var support = reputation.Support;

    switch (reputation.State)
    {
        case ReputationState.Neutral:
            // Can promote to Suspect or ConfirmedGood
            if (score >= 0.6 && support >= 10)
                newState = ReputationState.Suspect;
            else if (score <= 0.1 && support >= 100)
                newState = ReputationState.ConfirmedGood;
            break;

        case ReputationState.Suspect:
            // Can promote to ConfirmedBad or demote to Neutral
            if (score >= 0.9 && support >= 50)
                newState = ReputationState.ConfirmedBad;
            else if (score <= 0.4 || support < 10)
                newState = ReputationState.Neutral;
            break;

        case ReputationState.ConfirmedBad:
            // Can demote to Suspect (requires MORE evidence to forgive)
            if (score <= 0.7 && support >= 100)
                newState = ReputationState.Suspect;
            break;
    }

    // ... log state change and return ...
}

注意不对称@: @ it'}比被封锁更容易被堵 #.# ConfirmedBad → Suspect 需要@100}支持 @,}同时 Neutral → Suspect 这是故意的 - 它比怀疑更难原谅

时间衰落@ - @ 指数性遗忘

当图案变安静时 ,}它们向中立方向衰落

// From PatternReputation.cs:334-361
public PatternReputation ApplyTimeDecay(PatternReputation reputation)
{
    if (reputation.IsManual)
        return reputation;

    var hoursSinceLastSeen = (DateTimeOffset.UtcNow - reputation.LastSeen).TotalHours;

    if (hoursSinceLastSeen < 1)
        return reputation;  // Too recent to decay

    // Score decay toward prior (0.5 = neutral)
    // new_score = old_score + (prior - old_score) × (1 - e^(-Δt/τ))
    var scoreDecayFactor = 1 - Math.Exp(-hoursSinceLastSeen / _options.ScoreDecayTauHours);
    var newScore = reputation.BotScore + (0.5 - reputation.BotScore) * scoreDecayFactor;

    // Support decay
    // new_support = old_support × e^(-Δt/τ)
    var supportDecayFactor = Math.Exp(-hoursSinceLastSeen / _options.SupportDecayTauHours);
    var newSupport = reputation.Support * supportDecayFactor;

    return reputation with
    {
        BotScore = Math.Clamp(newScore, 0, 1),
        Support = newSupport
    };
}

默认的时间常数@ : @

  • 计分衰减@: @ @ 168 @ hours@(7_days @ I)}#-}分数移到中性, 经过一周的无活动之后
  • 支持衰变 □@: @ 336 @ hours@(14_ 天#)} @MS K4}信任在两周后下降 @MSKO5 @

这意味着一个已确认的 -bad IP 一个月静下来, 最终会下降回到中立.}不是因为它改革了#-}因为它的证据变得迟钝

背景维修处

缩略 ReputationMaintenanceService 正在运行三个定期任务@: @%

// From ReputationMaintenanceService.cs:48-129
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    _logger.LogInformation("Reputation maintenance service starting");

    // Load persisted reputations on startup
    await _cache.LoadAsync(stoppingToken);

    var decayInterval = TimeSpan.FromMinutes(60);    // Hourly decay sweep
    var gcInterval = TimeSpan.FromHours(24);          // Daily garbage collection
    var persistInterval = TimeSpan.FromMinutes(5);   // Persist every 5 minutes

    var lastDecay = DateTimeOffset.UtcNow;
    var lastGc = DateTimeOffset.UtcNow;
    var lastPersist = DateTimeOffset.UtcNow;

    while (!stoppingToken.IsCancellationRequested)
    {
        await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
        var now = DateTimeOffset.UtcNow;

        // Decay sweep: push stale scores toward neutral
        if (now - lastDecay >= decayInterval)
        {
            await _cache.DecaySweepAsync(stoppingToken);
            lastDecay = now;
        }

        // Garbage collection: remove old neutral patterns
        if (now - lastGc >= gcInterval)
        {
            await _cache.GarbageCollectAsync(stoppingToken);
            lastGc = now;

            var stats = _cache.GetStats();
            _logger.LogInformation(
                "Reputation stats: {Total} patterns, {Bad} bad, {Suspect} suspect",
                stats.TotalPatterns, stats.ConfirmedBadCount, stats.SuspectCount);
        }

        // Persistence: save to SQLite
        if (now - lastPersist >= persistInterval)
        {
            await _cache.PersistAsync(stoppingToken);
            lastPersist = now;
        }
    }

    // Final persist on shutdown
    await _cache.PersistAsync(CancellationToken.None);
}

垃圾收集器移除图案@: @%

  • {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}早年
  • 支持@≤ @ @ 1.0 @
  • 中立国

这阻止了 - memory 字典不受约束地成长,同时保存宝贵的学习模式@. {

SQLite 不是一个笑话 @ - @ it'# 这里完美

许多开发者对 PostgreSQL 或 Redis. 反射达标, 但对于此模式来说 @ , SQLite 是理想的@ MS K2}

  1. 在后面写- 消除瓶颈 - SQLite's s單一}-priterrationd doesn{'t matters 批量时不重要
  2. 当地储存 -无网络长期性,没有连接池
  3. 零配置 - 只是一个文件路径
  4. 适合边缘部署 -在草莓皮上奔跑
  5. 便携式 - 数据库只是您可以复制的文件

计划是最小的 :

CREATE TABLE IF NOT EXISTS learned_weights (
    signature_type TEXT NOT NULL,
    signature TEXT NOT NULL,
    weight REAL NOT NULL,
    confidence REAL NOT NULL,
    observation_count INTEGER NOT NULL DEFAULT 1,
    first_seen TEXT NOT NULL,
    last_seen TEXT NOT NULL,
    PRIMARY KEY (signature_type, signature)
);

CREATE INDEX IF NOT EXISTS idx_signature_type ON learned_weights(signature_type);
CREATE INDEX IF NOT EXISTS idx_confidence ON learned_weights(confidence);
CREATE INDEX IF NOT EXISTS idx_last_seen ON learned_weights(last_seen);

如果您需要更大的比例@ , @ 换成 PostgreSQL.} 如果您需要 HA 或复制@ MPK2} 替换到 Redis 或者分布的缓存 @ MS K3} 架构将“ '} t change” @- 只要连接字符串\ . SQLite 是边缘部署的默认值 @ IMK7} 而不是宗教=.}

DISE Tie-在 @ - 失败作为进化

如果 DiSE 日志 是完整的进化引擎,}这个缓存模式是 MItochondriaMS K1}最小的一块仍然在限制下 像进化一样的小块_.}

这种模式在最起码的级别上执行DISE原则 @:

  • 资源制约 @→ 选择压力
  • LRU驱逐 {\fn华文楷体\fs16\1cHE0E0E0}生还者是适龄者
  • 时间衰变 → 忘记使适应成为可能
  • EMA 更新EMA → 通过观察变异
  • 歇歇症 通过抵抗变革实现稳定

一个完整的缓存是 @ '@ title: listbox 进化压力“. 系统自我”“-Opptiminises:热签名” “MS K3冷签将“,”逐出,行为记忆与实际重要内容趋同。”

没有 ML 训练@.没有外部模型 @. 只是像生活系统一样的建筑_.

“-”简单结构“, 新兴行为

整个图案归结为“:”

  1. Cache是真理之源, @ -_ sub MS K1_ milli second access
  2. 立即写入更新缓存@ , @ @ label 无屏蔽 I/O
  3. Sliding 过期失效自动提供 LRU @-# 建在@._NET
  4. 宽幅大小造成选择压力 @- 溢出突出焦点
  5. 背景水流使 SQLite 同步 最终的一致是好的
  6. 时间衰变可以忘记 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}失踪的证据

你的小行为商店的行为 更像一个生活系统 比CROUD.}它记得什么重要 它忘记了什么

最小架构@ → @ 突发的正确性 @ MS K1 @ 上移@→ @ 更好地聚焦 @ . @ 压力: →稳定性 @.

如果您想在动作中看到此操作@ , @ check out 多数是卢希德.}(机器人检测) *-和 DISE 建筑系列 更深层次的哲学

链接链接链接

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.