抗日战争系列导读:从帝国扩张到战争遗产
1937年12月,南京陷落;1938年秋,武汉和广州相继失守。日本占领中国首都和重要经济、交通中心,却没有得到结束战争的政治结果。中国继续抗战,也并不意味着还能按照战前的方式生活和治理。政府、工厂和学校迁移,粮食、货币和劳动力的分配改变,大量人口流离失所。理解战争为何延续,既要解释军队能否作战,也要解释一个社会怎样在巨大损失中继续提供作战所需的资源。 这套系列沿着战争发生、扩大、持久化和结束的过程展开,再讨论它留下的制度与记忆。日本把侵略说成“解放亚洲”,是其中需要专门解释的问题。它有助于说明扩张者怎样定义目标、组织服从和排除反对,却不足以代替中国如何抵抗、普通人怎样经历战争、国际力量怎样改变战局的历史。 十篇文章可以依次阅读,也可以从某个问题进入。军事进程主要集中于第二、三、四、八、九篇;第五至七篇暂时放慢时间顺序,分别讨论社会资源、占领统治与战争观念。它们解释的是前后各阶段都在起作用的条件,并非脱离战场的附录。 从哪里开始读 表1:抗日战争系列篇目与各篇边界。 篇次 文章 本篇主要解释什么 1 战争从何而来 晚清以来地区秩序如何改变,帝国扩张与中国国家建设怎样...
以色列如何建国:从民族运动到托管终结
1948年5月14日下午,本古里安在特拉维夫宣布以色列建国,随后返回司令部讨论战争。他当天的日记记录了一个具体分歧:是否加强行动,夺取通向耶路撒冷的胡勒达—沙尔哈盖道路周围地区。参谋人员认为兵力不足、不清楚敌方计划,几乎一致反对。在宣布国家的那一天,政治领导人仍须解决补给线和指挥权限问题;他甚至写道,还没有习惯把原来的行政机构称作“政府”。国家名称在改变,支撑它的组织与已经展开的战争则有更长的历史。本古里安日记,1948年5月14日 以色列的建立,是民族运动、移民社会、帝国制度、国际决策与战争动员共同形成的结果。1947年末,巴勒斯坦已经陷入社区间战争;1948年5月英国托管结束、以色列宣布独立以及阿拉伯国家正规军介入,使战争进入新的阶段。本篇追溯这些条件怎样形成,止于这个转折。后篇将从1947年末重新展开战事,重建道路争夺、城市陷落、难民迁移与国家军队交战,延伸至1949年。联合国巴勒斯坦委员会,S/676 历史联系与现实居民 犹太人与这片土地的历史联系,有独立于现代民族叙事的材料。亚述王室铭文记录了公元前九至八世纪的以色列王国,并将它与南部犹大区别;前722年撒马利亚...
第一次中东战争:从道路袭击到多战线战争
1947年11月30日,两辆犹太客车先后遇袭。1948年5月,埃及、外约旦等国的正规军进入巴勒斯坦。两个日期相隔五个多月,其间的战争已改变当地社会:街区被隔开,班车变成武装护航车队,沿路村庄和高地成为攻击目标,地方武装的战斗被纳入更大的地域控制计划。以色列宣布建国时,海法、雅法、萨法德等城市的军事和人口格局已经发生重大改变。本篇是建国史系列的第二篇,从这些中间步骤写到1949年的停战;S01S08S19 下文的沿海、耶路撒冷走廊、中央地区、北部和南部,是便于读图的地域划分,并非一套自1947年底就固定存在的战区司令部。实际指挥单位包括地方守备机构、旅、临时行动指挥部,以及后来能够协调多个旅的战线指挥机构。例如纳赫雄是跨单位集中兵力的编组,哈梅茨联合数个地区旅,达尼、约阿夫又使用更大的兵力组合。地名第一次出现附常见异名;E编号可以在文末详细事件表中定位,S编号链接到来源。S14S55S30S35 两辆巴士,和一个不能承担全部解释的起点 常见的“一辆巴士遇袭”省略了第二次袭击。莫里斯《1948》第76页记载:11月30日约8时20分,第一辆车在法贾(Fajja)、卡法尔西尔金...
俄乌战争的根源:国家形成、领土争议与欧洲安全秩序
俄乌战争不是古代共同起源或一次苏联划界的自然结果。乌克兰国家形成与俄罗斯对周边秩序的要求,在地区利益、政权危机和北约关系中发生冲突;2014年中央权力断裂、俄罗斯军事介入和地方武装动员,使争议转成战争。明斯克试图把停火同乌克兰内部政治安排结合起来,却未解决武装控制与政治重整的冲突;2022年俄罗斯进一步选择全面战争。历史联系和安全忧虑能够解释部分动机,不能单独证明这些行动不可避免。本文资料截止于2026年10月21日,分别考察2014—2021年的冲突与2022年后的全面战争。 国家如何形成 科切加罗夫指出,古罗斯宗教文化传统跨越后来的政治边界延续,但波兰—立陶宛制度及地方自治又使乌克兰地区积累了不同经验。哥萨克精英可以接受共同宗教传统,同时维护地方权利。共同继承与后来民族分化并不矛盾,也不能据共同来源推出永久统一。科切加罗夫的解释 普京2021年的文章也承认乌克兰人是古罗斯继承者,承认乌克兰名称、乌语文学与哥萨克自治。他否定的是独立于俄罗斯人的乌克兰民族观念的历史基础,并把现代乌克兰及其疆域归于苏联安排。但他又承认一个民族的一部分可以形成独立民族,个人可以选择民族身份,亲...
后端系统工程 08:群消息扇出与成员版本
后端系统工程 08:群消息扇出与成员版本 本批导航:00 技术方案怎样接受验证|01 API 契约与业务不变量|02 负载模型与容量预算|03 单库基线与故障实验工具|04 持久化边界|05 长连接接入|06 发送确认|07 排序与增量同步|08 群消息扇出|09 多设备已读|10 网关故障与路由收敛|11 撤回与集成验收 单聊的一条消息只送达两个人的几台设备,群消息要送达几十到几百名成员的设备。第 02 篇的模型已经表明,扇出带来的送达成本远大于消息写入本身,而且随群规模线性增长。本篇处理群消息的两个问题:送达成本怎样控制,以及在成员不断加入、退出的情况下,每条消息应该送给谁、谁可以读取它。 第二个问题比第一个更容易出错。成员变更与消息发送是并发的;推送是异步的,从消息提交到推送发出之间,成员可能已经变化。若推送目标按“推送时刻的成员”计算,刚退群的成员可能收到退群之后的消息,刚入群的成员可能收到入群之前的消息。本篇按事件序号计算成员资格,使这两种情况都不会发生。 1. 需求与不变量 编号 不变量 对应需求 F1 序号为 s 的事件,只推送给在 s 上属于成员...
后端系统工程 09:多设备已读与未读状态
后端系统工程 09:多设备已读与未读状态 本批导航:00 技术方案怎样接受验证|01 API 契约与业务不变量|02 负载模型与容量预算|03 单库基线与故障实验工具|04 持久化边界|05 长连接接入|06 发送确认|07 排序与增量同步|08 群消息扇出|09 多设备已读|10 网关故障与路由收敛|11 撤回与集成验收 一个用户同时登录手机和电脑时,“这条消息看过了吗”有两个不同的问题:这台设备上有没有这条消息,以及这个人有没有读过它。前者属于设备,后者属于用户。用户在手机上读完消息,电脑上的未读数应该消失;但电脑并没有因此获得这些消息的数据,如果它此后离线,打开会话时仍然要从服务端拉取。 本篇把两类状态分开存储:送达游标按设备,已读位置按用户;未读数不存储,而是在查询时由已读位置和事件推导出来。重点处理三种异常:两台设备的已读上报乱序到达,设备重装后旧安装发来的确认,以及设备从旧的本地备份恢复后上报一个更小的游标。 1. 需求与不变量 编号 不变量 观察位置 M1 送达游标按 (设备, 会话) 记录,单调,不超过 head device_cursors ...
后端系统工程 10:网关故障后的重连与路由收敛
后端系统工程 10:网关故障后的重连与路由收敛 本批导航:00 技术方案怎样接受验证|01 API 契约与业务不变量|02 负载模型与容量预算|03 单库基线与故障实验工具|04 持久化边界|05 长连接接入|06 发送确认|07 排序与增量同步|08 群消息扇出|09 多设备已读|10 网关故障与路由收敛|11 撤回与集成验收 第 05 篇处理的是单个连接的生命周期:握手、心跳、慢接收端,以及同一设备的新连接取代旧连接。那里的故障都是局部的,一次只影响一个连接。网关进程整体失效则不同。一个进程上挂着成千上万个连接,进程消失的瞬间它们同时断开,随后几乎同时尝试重连。这时有三个问题需要回答: 死掉的网关没有机会清理自己的路由记录,谁来清理,什么时候清理? 大量设备同时重连,怎样避免它们把剩下的网关和数据库一起压垮? 重连过程中网络会产生延迟和重复。某个旧握手在新连接建立之后才到达,怎样保证它不会把设备的归属改回已经失效的连接? 本篇在第 05 篇的路由声明之上增加三样东西:网关租约、握手准入和带抖动的重连退避。另外补上计划内下线(排空)的流程。所有结论都来自本地多进程实验:...
后端系统工程 11:撤回、历史保留与消息系统集成验收
后端系统工程 11:撤回、历史保留与消息系统集成验收 本批导航:00 技术方案怎样接受验证|01 API 契约与业务不变量|02 负载模型与容量预算|03 单库基线与故障实验工具|04 持久化边界|05 长连接接入|06 发送确认|07 排序与增量同步|08 群消息扇出|09 多设备已读|10 网关故障与路由收敛|11 撤回与集成验收|下一篇 12 有界连接池与等待取消 前面七篇都在处理一条消息“怎样写进去、怎样送出去”。本篇处理消息写入之后的变化:发送者撤回、保留期满后被删除、整个数据库从备份恢复。三者有一个共同点,都会和前面建立的不变量发生冲突。 第 07 篇假定已提交事件不可变,客户端可以只按序号增量同步。撤回却要求修改一条已经被别人收到的消息。 第 04 篇保证会话内序号从 min_seq 起连续,第 01 篇保证同一请求键只产生一条消息。保留清理要删除的,正好是序号和请求键的载体。 备份恢复会把数据库带回过去某个时刻,所有不变量都需要在副本上重新检查,而不能默认成立。 本篇的另一项任务是集成验收:把第 04–11 篇的全部 71 项检查与第 00 篇的需求卡 R...
后端系统工程 00:一份技术方案怎样接受验证
后端系统工程 00:一份技术方案怎样接受验证 本批导航:00 技术方案怎样接受验证|01 API 契约与业务不变量|02 负载模型与容量预算|03 单库基线与故障实验工具|04 持久化边界|05 长连接接入|06 发送确认|07 排序与增量同步|08 群消息扇出|09 多设备已读|10 网关故障与路由收敛|11 撤回与集成验收 评审技术方案时,常见的提问是“这个设计能不能扛住”“消息会不会丢”。这些问题回答不了,原因通常不在于设计者不够仔细,而在于方案本身没有给出可以判定的陈述:“不丢消息”没有说明在哪一刻之后不丢,“能扛住”没有说明扛住的是什么负载、用什么去观察。一份能接受验证的方案,必须让每一句承诺都能落到一个观察位置和一个判定方法上,判定结果只有成立或不成立两种。 本篇为整个系列确定写方案的方法。对象是后面 04–11 篇要逐步实现的最小即时通信服务(下文简称“消息服务”),使用合成的团队协作场景:成员、会话、设备、消息,域名统一为 example.test。本篇产出三件东西:一张需求卡、一张状态表、一组设计决策记录,以及检查需求卡格式与证据对应关系的脚本 exampl...
后端系统工程 01:API 契约与业务不变量
后端系统工程 01:API 契约与业务不变量 本批导航:00 技术方案怎样接受验证|01 API 契约与业务不变量|02 负载模型与容量预算|03 单库基线与故障实验工具|04 持久化边界|05 长连接接入|06 发送确认|07 排序与增量同步|08 群消息扇出|09 多设备已读|10 网关故障与路由收敛|11 撤回与集成验收 第 00 篇把消息服务的承诺写成了需求卡 R1–R7。需求卡说明系统保证什么,接口契约说明调用方在每一种回复下可以相信什么。两者之间有一个容易被忽略的落差:服务端内部即使做到了“同一请求只写一行”,如果回复格式不能让客户端区分“首次成功”“重复请求的成功”“请求被拒绝且不应重试”“结果未知、应当重试”,客户端仍然会做出错误决定,例如对一条已经提交的消息弹出“发送失败”。 本篇定义消息服务的请求格式、回复格式和错误码,重点处理三类异常请求:重放、越权和过期。所有判定都落到可执行检查上,检查编号来自第 04、06、11 篇的实验。 1. 契约要回答的问题 调用方每发出一次请求,最终处在以下四种状态之一: 收到成功回复:操作已生效,回复中的标识(seq、m...













