This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
学习LRUs @-}当超能力使你的系统变得更好时
Tuesday, 09 December 2025
多数系统在超载后会退化@. @ 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.
同步战略
关键的观点是 完全同步是有必要的系统容忍漂移,因为... ...:...
- DB 的缓存遗漏未重装入 - 如果条目被驱逐@, 下一读取新数据
- 滑动过期处理柄的渐变 @ - @ {% 1} 未进入的条目@ MS K1 @ minutes auto @ MPK2 @ evict
- 装甲部队的更新 - 定期压缩推出旧条目
- 在联合后写-}更新 @-多个快速更新变成 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}
- 在后面写- 消除瓶颈 - SQLite's s單一}-priterrationd doesn{'t matters 批量时不重要
- 当地储存 -无网络长期性,没有连接池
- 零配置 - 只是一个文件路径
- 适合边缘部署 -在草莓皮上奔跑
- 便携式 - 数据库只是您可以复制的文件
计划是最小的 :
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 训练@.没有外部模型 @. 只是像生活系统一样的建筑_.
“-”简单结构“, 新兴行为
整个图案归结为“:”
- Cache是真理之源, @ -_ sub MS K1_ milli second access
- 立即写入更新缓存@ , @ @ label 无屏蔽 I/O
- Sliding 过期失效自动提供 LRU @-# 建在@._NET
- 宽幅大小造成选择压力 @- 溢出突出焦点
- 背景水流使 SQLite 同步 最终的一致是好的
- 时间衰变可以忘记 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}失踪的证据
你的小行为商店的行为 更像一个生活系统 比CROUD.}它记得什么重要 它忘记了什么
最小架构@ → @ 突发的正确性 @ MS K1 @ 上移@→ @ 更好地聚焦 @ . @ 压力: →稳定性 @.
如果您想在动作中看到此操作@ , @ check out 多数是卢希德.}(机器人检测) *-和 DISE 建筑系列 更深层次的哲学
链接链接链接
- Bot探测器检测介绍 -使用这些模式的系统
- DiSE 架构概览 -通过压力控制进化
- 现代CQRS和事件观察 当您需要时, - @ 整个图案@ MS K1 @ I) @
- GitHub: mostlucidMS K1bot 检测器 -}完整的源代码
- NuGet 软件包 - 安装它