内存化系统如何设计?

发布时间:2026/7/2 3:05:48

内存化系统如何设计? 一、内存化系统不是缓存这是很多系统一开始就设计偏的地方。缓存系统里DB 是权威数据源内存只是加速丢了可以随时重建。内存化系统不一样内存就是权威数据源DB 只是持久化副本内存一乱系统就乱。传统系统内存化系统数据在数据库数据在内存DB 是主角DB 是备胎扛不住高并发天生低延迟二、核心内存模型怎么设计内存里存什么不要存 DTO不要存 VO不要直接映射表结构。内存里只存业务状态最小集合。以账户系统为例class AccountState { long accountId; long balance; // 用最小单位比如分 long frozen; int version; // 内存版本号 }两个要点使用内存占用少的结构不放无关字段。用什么结构内存结构取决于业务形态除了业务数据本身可能还需要索引结构。HashMap / ConcurrentHashMap查找 O(1)JVM 友好90% 场景够用MapLong, AccountState accounts new HashMap();数据量特别大的场景可以用Long2ObjectMap避免 Long 装箱减少 GCLong2ObjectOpenHashMapAccountState accounts;三、并发度不是线程越多越好分片 单线程请求 ↓ ┌──────────────────┐ │ Router(按 key) │ └──────────────────┘ ↓ ↓ Shard-1 Shard-2 Thread ThreadRouter 按 key 分片int shard (int) (accountId % shardCount); executor[shard].execute(() - handle(cmd));每个 Shard 内部一个线程、一个内存 Map、无锁。这是撮合、账本、风控系统里用得最多的模型。为什么不用锁锁隐藏了并发复杂度状态一致性难验证性能随并发退化。单线程分片模型保证了顺序确定性这是内存化系统能跑稳的关键。四、内存数据变更禁止直接改状态account.balance - amount;没来源不可回放不可审计。Command → Event → State外部输入 Command内部转成 Event 落盘内存中维护 State// Command class DebitCommand { long accountId; long amount; } // Event class BalanceChangedEvent { long accountId; long delta; long before; long after; } // Apply void apply(BalanceChangedEvent e) { AccountState s accounts.get(e.accountId); s.balance e.after; s.version; }所有变更都有记录可以重放可以异步落盘。五、日志和快照WAL 的基本要求顺序写先写日志再返回成功log.append(event); apply(event);日志内容至少包含业务 key、变更前后值、全局递增序号。快照怎么做不要用 JVM heap dump 或 Java 序列化。正确方式是显式序列化业务字段for (AccountState s : accounts.values()) { write(s.accountId, s.balance, s.frozen, s.version); }明确字段可跨版本可校验。重启恢复流程加载最新快照 ↓ 定位日志 offset ↓ 顺序回放 event ↓ 校验版本号这个流程必须 100% 自动化完成不能依赖人工干预。六、单点故障主从复制的是 EventMaster: 生成 Event ↓ 复制 Event ↓ Slave: apply(Event)不是序列化整个 Map也不是网络同步内存对象。切主的条件日志 offset 对齐、内存版本一致。条件不满足宁可不可用也不乱切。双活 / 多活同一份数据多实例共同维护。难点在顺序一致性和冲突解决。可以考虑 sofa-jraft 框架支持主从同步和自动选主。七、内存不够了怎么办拆是第一优先级按用户分片或业务分区。内存系统的扩展能力90% 靠拆。热冷分离热数据留内存冷数据落 SSD 或 DB。结构压缩用 long 替代 BigDecimal在最小计量单位前提下用 bit 表示状态enum 转 int。堆外内存Chronicle Map、Unsafe / ByteBuffer收益高但复杂度陡增谨慎使用。八、Java 常用框架场景框架用途单机缓存Caffeine热数据事件队列Disruptor单线程模型同步数据sofa-jraft选主 日志同步序列化protobuf数据写入与读取

相关新闻