理解MySQL的MVCC

我们为什么需要 MVCC ? 没有MVCC(多版本并发控制 Multi-Version Concurrency Control)的情况下,面对数据库事务中"读某一条数据"的行为,我们只能加锁。这个锁可以是共享锁/排他锁,保证"我读的时候没人过来写",避免脏读(读到和最终结果不一致的数据)。然而一旦加锁,其他线程就要等,一等并发效率就直线下降。 MVCC 的思路是:读的时候不加锁,而是通过"版本"来判断一条数据对我来说能不能读。 每一行数据的三个隐藏字段ba 每一条数据除了业务字段外,还有三个隐藏字段: DB_TRX_ID 最近一次插入/更新/删除该行的事务id DB_ROLL_PTR 回滚指针,指向这行数据在 undo log 中的上一个版本 DB_ROW_ID 隐藏主键,仅在表没有定义主键时才会生成 undo log 把同一行数据的历史版本串成一条链,DB_ROLL_PTR 就是链上的指针,出问题时可以顺着它一路往回找老版本。 Read View:读之前先拍个快照 在真正读数据之前,我们会先生成一个快照,叫做 read view。它记录了这几样东西: m_ids 生成快照那一刻,所有"活跃"(未提交)的事务id列表 min_trx_id m_ids 里最小的那个id max_trx_id 系统里下一个将要分配的事务id(也就是目前已知最大事务id + 1) 注意 max_trx_id 不是"当前活跃事务里最大的那个",而是"还没被任何事务用过的、未来第一个可用的id"——因为事务id是全局递增分配的。 这里要先说清楚一件容易被忽略的事:read view 什么时候生成,在不同隔离级别下是不一样的。 READ COMMITTED(读已提交):每次执行 SELECT 语句都重新生成一个 read view REPEATABLE READ(可重复读,MySQL默认):只在事务内第一次执行 SELECT 时生成一次,之后整个事务复用同一个 read view 这个区别直接决定了"我这次读,能不能看到别人事务提交的新数据"——RC 每次都能看到最新提交的结果,RR 则始终锁定在事务开始时的那个快照上,这也是可重复读名字的由来。 拿到 read view 之后,怎么判断某一行能不能读 现在回到最初的问题:我们要读一行数据,它的 DB_TRX_ID = 200。这条数据被事务200修改过,我们能不能读到它,要按顺序做以下判断: ...

2026-07-28 01:40:09 PM · 1 分钟

来,总结一下我遇到的完美对冲

生活相关 穷的时候没钱乱买东西,正好也没地方放。。因为穷所以租的房子小,购物欲和收纳空间同步受限,消费主义完成了自我抵消; 辣的东西容易吃多,但辣到一定程度嘴会痛到吃不下去——过量摄入的风险被摄入过程本身劝退了,自带限流熔断; 越常用的汉字笔画越简单(“的、一、是、了”),越生僻的字才越复杂。使用频率和书写成本完美负相关,语言自己完成了性能优化; 睡眠充足的人精力好,精力好就更有自制力早睡,早睡又保证了睡眠充足——自律的人连生物钟都在帮他滚雪球,简直完美; 脸皮薄、不好意思拒绝别人的人,往往朋友越来越多(都觉得他好说话),结果他独处恢复精力的时间越来越少——社交资源与心理能量天然对冲,性格自己给自己设了天花板。当一个人的社交资源有了新的高度,就必然要牺牲内在的深度; 水在4℃时密度最大,所以冬天湖面结冰而湖底保持4℃,鱼不会冻死; 哲学相关 维基百科的词条越中立,读起来越无聊;越有立场的词条,读起来越生动,但越不可靠——可信度与传播力在信息熵里互相拉扯,真相常常干不过叙事; 越是深奥的知识说得越绕,越绕的话越没人愿意读完——高深的知识自带传播衰减(好像跟上一条差不多哈😑); 摄影相关 相机光圈更大,进光量更大,画质会变得更好,快门速度也可以更快。对于追求氛围感的摄影,还能带来极致的虚化感,简直完美。如果是拒绝虚化效果的写实摄影,那就没这个好处了; 胶片按一张亏一张,所以每次抬手都要想清楚,出片率反而比数码高——成本是最好的构图老师; 编程相关 Kafka 消息可能重复投递是个缺点,但这逼着你把消费者写成幂等的;写成幂等之后,重试、宕机恢复、手动补数据全都不怕了。一个不可靠性逼出了一整套可靠性; JAVA使用递归,代码让人看得头大,但是递归又有StackOverFlow的隐患,一般好的程序员不会写递归代码,正好解决了读递归代码脑壳疼的问题; 布隆过滤器会误判"存在",但绝不误判"不存在",而挡缓存穿透需要的正是后者——一个不精确的结构在这个场景里精确得刚刚好; 开源项目用的人越多,bug 被发现修得越快,越稳定就越多人用

2026-07-25 07:21:40 PM · 1 分钟

过家家项目:如何设计抢红包

在我的项目“过家家”里,有一个抢红包的功能。功能类似微信抢红包。 抢红包的基本逻辑 v1(低并发)抢红包时实时使用二倍均值法计算,只使用MySQL 1. 红包创建流程 用户发红包时,指定总金额与红包个数 系统将总金额拆分为指定数量的红包 红包数量约束: 最少为 1 个 最多不能超过群成员数量 2. 红包金额分配策略 单个红包:不进行随机计算,抢到即获得全部金额 多个红包:采用二倍均值法进行随机分配 当前用户最大可抢金额 = 剩余金额 / 剩余人数 × 2 实际可抢区间为 [0.01, 最大可抢金额 - 0.01] 下限 0.01 元:保证每个抢到的用户都有收益 上限减 0.01 元:保证剩余红包仍有余额可抢 边际示例:10 元红包 2 人分,第 1 人可抢区间为 [0.01, 9.99] 3. 数据持久化与防刷控制 红包创建后入库存储 发红包限流:同一用户 10 秒内仅允许发送 1 个红包,防止手抖误操作 4. 抢红包并发控制 防重复抢:在 redpacket_grabs 表中建立 (userId, redpacketId) 联合唯一索引,确保同一用户对同一红包仅能抢一次 防超卖:采用数据库乐观锁机制 更新 redpacket 表时,必须同时满足: remaining_count > 0 remaining_amount >= 本次扣减金额 5. 方法缺点 每次请求直接打数据库,导致响应时间没有访问内存快 每次请求都会使用二分均值法计算抢到的金额,并且做超卖判断,比较麻烦 v2 (高并发)红包创建好了就已经固定了抢红包的数量和个数,加入Redis 大致流程 ...

2026-07-25 11:09:53 AM · 2 分钟

如果我们死后去哪里被科学家揭晓了,世界会发生什么?知晓答案的我们会迎来灾厄还是幸福?

如果我们死后去哪里被科学家揭晓了,世界会发生什么? 知晓答案的我们会迎来灾厄还是幸福? 我能想到的几种答案: 答案1:原来我们死后会进入一个等待队列,会在这个星球上失去一切记忆地随机再次以人形重生 按当前地球人口的增速来看,可能还没到"需要等"的那一步,我们一领便当,便当都没来得及吃,就从另一个母亲的肚子里哇哇落地了。 如果重生被证明无需任何代价,即,你刚没意识,就突然从另一个人肚子里醒来。那么这会迎来几个相当有可能的后果: 后果1(火速重开版) 长到知道什么是财富差距的年龄,发现自己家里一贫如洗,赶紧找把枪把自己枪毙。人生变成一场无限次数的抽卡游戏,而"重开"这个梗第一次拥有了字面意义。各国紧急立法管制一切危险物品,但拦不住——你没法用"珍惜生命"去劝一个知道生命是复读机的人。 后果2(恶人的崛起) 反正人一辈子就是一死一循环的事,赶紧把坏事做尽,死比坐牢强。刑法的威慑力一夜清零:无期徒刑?我下一世照样是个白白净净的婴儿。死刑甚至成了越狱手段。人类引以为傲的整套惩罚体系,原来押的全是"人只活一次"这一个注。 后果3(世界和平共同富裕) 原来我们无论如何都要重返这个世上,我们应该互帮互助,每个人都来得开心去得开心,没有战争,没有争抢,因为不必,我们只需开心地永恒着。你今天往河里倒的垃圾,五十年后会流进你下一世的水杯;你今天投下的炸弹,炸的可能是你自己明天的产房。环保和和平不再需要道德说教——它们成了纯粹的、自私的、无可辩驳的利己行为。 这三种后果会同时发生。人类大概要用两百年惨烈地筛选,最后活下来的文明版本,多半是后果3。不是因为人性本善,而是因为前两种玩法的玩家,会一遍一遍重生在被自己搞烂的世界里,直到玩明白为止。 答案2:还是随机重生,但是谁跟你说你还是人的形态了? 重生池是全物种共享的。按生物量算一算就会脊背发凉:地球上全人类不到六亿吨,蚂蚁跟我们差不多重,线虫、浮游生物、细菌加起来是我们的几千倍。也就是说,在轮回抽卡池里,“人类"是个出货率低到离谱的SSR——你这一世能坐在这里刷手机,已经是欧皇本皇了。 后果1(全民吃素版) 牛肉面馆一夜倒闭,因为那碗牛肉有万分之一的概率是你上一世的班主任。拍死一只蚊子要不要按"过失"处理成了立法难题,夏天变得极其难熬。渔业畜牧业连夜转型,人类食谱倒退回采集时代——好在植物暂时还没被查出在池子里。 后果2(体验派的狂欢) 也有人开始期待死亡:“下辈子想抽个信天翁,环游世界不用签证。““我想当一棵红杉,站两千年,看你们轮回。“殡仪馆的悼词从"一路走好"变成"祝你出货”。 后果3(人类中心主义崩塌) “众生平等"从宗教口号变成物理事实。动物园关门,实验室白鼠获得赔偿性放生。人类第一次意识到:我们不是地球的主角,只是暂时借了一副带拇指的身体。 答案3:还是随机重生,但是谁跟你说是在地球了? 重生范围:全宇宙。可观测宇宙少说两万亿个星系,你重生回地球的概率,约等于连续一百次中彩票头奖。 后果1(天文学成为殡葬行业) 天文台门口排起长队,家属握着天文学家的手:“您看我妈她……大概往哪个方向去了?“墓碑不再朝南,改朝室女座超星系团。清明烧纸的时候顺便烧一台射电望远镜模型,聊胜于无。 后果2(宇宙级躺平) 大家突然不焦虑了。房贷?内卷?KPI?下辈子我可能是猎户座旋臂上一坨快乐的星际气体,在零下两百七十度里舒展十亿年。这辈子这点破事,格局小了。 后果3(宇宙级恐慌) 也有人算了另一笔账:宇宙的绝大部分是真空、辐射和孤独。重生成一颗在星系间漂流一百亿年的氢原子——这到底算重生,还是无期徒刑?哲学系连夜开题:《论"存在"是否必须以"体验"为前提》。答辩没人通过,因为没人敢下结论。 答案4:完了,发现原来我们一生做的好事坏事真的有积分系统计算着 后果1(功德通货膨胀) 斑马线前扶老奶奶的队伍排出两公里,老奶奶成为稀缺资源,出现职业"被扶员”,时薪不菲。公交车让座要靠抢,献血站限流,捐款平台崩溃。善良第一次出现了产能过剩。 后果2(动机审查悖论) 科学家紧急补充说明:系统会识别动机,刷分无效。全人类当场哀嚎——那我现在做好事,到底是出于善良,还是出于"想让系统觉得我出于善良”,还是"知道系统会审查动机所以努力让自己真诚"的三阶套娃?这成为新时代哲学第一难题,康德全网售罄。 后果3(历史清算) 有人翻出自己一生的流水账,发现小学偷拿同桌一块橡皮被扣了2分,至今没涨回来,当场崩溃。也有人发现自己随手做的一件小事——雨天给流浪猫挪了个纸箱——加的分比捐一栋楼还多。人们终于摸清了系统的口味:它不看金额,看你当时以为没人看见。 后果4(宗教界的复杂心情) 各大宗教一半在庆祝"早说过了”,一半在紧急对账——教义里的计分规则和实测数据对不上,误差还不小。神学院连夜改开数据分析课。 答案5:完了,原来所有的你你我我,最后只是一个人在扮演不同的角色…… 科学家沉默了很久才公布这一条:宇宙里自始至终只有一个灵魂。它在时间里反复折返,出演每一个出生过的人。你是你,也是你妈,也是你小学同桌,也是那个在网上骂你的人。所谓"他人”,是同一个演员换了戏服,隔着时差,跟自己对戏。 后果1(吵不动了) 一切争吵在物理层面失去意义。你骂的是自己,你卷的是自己,你插队挤开的还是自己。战争成了世界上最荒诞的行为艺术:一个人,分饰两军,隔着战壕朝自己开炮。军队解散那天没有仪式,因为实在不知道该向谁投降。 后果2(爱变得很奇怪) 有人崩溃了:那我爱我妻子,算不算终极自恋?情书还怎么写——“致我自己的另一场演出”?但也有人想通了:正因为对面是你,爱才第一次有了保底。你永远不会真正失去任何人,散场的演员会在另一场戏里换个脸回来,还是你。 后果3(终极共情,或终极孤独) 白天,人们对彼此前所未有地温柔——伤害任何人都是自残,帮助任何人都是自救,“己所不欲勿施于人"从劝诫变成了同义反复。夜里,同一批人失眠:如果所有人都是我,那这个宇宙里,其实只有一名观众。掌声是我的,嘘声是我的,连"孤独"这个词,也是我发明出来说给自己听的。 答案6(番外):论文无法复现 宣布答案的第三天,另一组科学家发了篇预印本:《关于死后去向实验的复现失败报告》。 全世界长舒一口气。 原来人类需要的从来不是答案,而是那一点点"不知道”。不知道,才有宗教,才有哲学,才有半部文学史,才有清明烧下去的纸钱,才有"来世再见"这句既是狠话又是情话的话。 死亡是人类地图上最后一块没被标注的荒野——我们一边怕它,一边偷偷指望它永远别被开发。 所以真正的问题也许从来不是"我们死后去哪里”。 而是:答案揭晓之后,我们还能不能好好活。 灾厄和幸福大概都会来,按人头随机发放—— 就像重生一样。

2026-07-25 12:48:15 AM · 1 分钟

Kafka 学习笔记

偏移量索引 高可用 ISR机制

2026-07-18 04:01:26 PM · 1 分钟

DB MQ Redis 常见实践

一、读路径:Cache Aside(旁路缓存) 先查 Redis,命中就返回;未命中查 DB,回写 Redis 后返回。 Redis 三件套 问题 场景 解法 穿透 查一个不存在的 key,每次都打到 DB 缓存空值(短 TTL) + 布隆过滤器 + 参数校验 击穿 某个热点 key 过期,瞬间大量请求打到 DB 分布式锁只放一个线程回源 + 逻辑过期(异步重建) + 热点 key 不过期 雪崩 大批 key 同时过期或 Redis 宕机 TTL 加随机抖动 + 多级缓存(Caffeine + Redis) + 熔断降级(Sentinel) + 集群/哨兵高可用 二、写路径:先写 DB,再删缓存 不用"更新缓存"而用"删除缓存":避免并发写导致的脏数据,也避免为不会被读的数据做无用计算(lazy loading)。 为什么是"先 DB 后删"而不是"先删后写 DB"? 先删缓存,在写 DB 的间隙可能有读请求把旧值重新加载进缓存,且这个旧值会一直存在直到过期。 但先写后删仍有极小概率不一致(读线程读到旧 DB 值 → 写线程写 DB + 删缓存 → 读线程回写旧值)。兜底方案: ...

2026-07-16 10:20:21 PM · 3 分钟

AI Coding 省流指南

1. 核心大招:强制“增量输出”(Diff-Only) 这是节省 输出 Token 最有效的手段。默认情况下,大模型喜欢把整份代码文件重新写一遍,即便它只改了一行。 笨办法:“帮我修改这个文件的 bug。”(模型直接吐出 500 行代码) 妙招:在 Prompt 中明确限制输出格式。 Prompt 模板: “请只输出修改过的代码片段。未修改的部分请用 // ... 保持不变 ... 或 # ... existing code ... 代替。如果可以,请直接以 Git Diff 的格式提供修改方案。” 2. 输入“骨架”而非全量代码(Skeleton Prompting) 当你需要让模型理解你的项目结构或某个工具类时,不要直接把几千行的源文件贴过去。 妙招:只给模型提供类型定义(Types/Interfaces)、函数签名(Function Signatures) 或 骨架代码。 例如(TS/JS): // 不要贴整个实现,只给这个: interface UserService { getUser(id: string): Promise<User>; updateProfile(id: string, data: Partial<User>): Promise<boolean>; } 模型只需要知道“有什么方法可用”以及“入参和出参是什么”,并不需要知道你内部复杂的 SQL 是怎么写的。 3. 巧用 XML 标签(对 Claude 尤为有效) Claude 对 XML 标签(如 <code_>)有着极强的敏感度。用 XML 标签包裹代码和指令,不仅能提高准确率,还能减少解释性废话。 <system_instruction> 你是一个极简主义的编程助手。请直接输出代码,不要解释,不要说“好的,我为你准备了以下代码”。 </system_instruction> <source_code> // 贴入你的核心代码 </source_code> <task> 重构上面的代码,提高运行效率。 </task> 省流原理:明确的结构让模型不需要在 Prompt 里猜测“哪里是代码,哪里是要求”,从而大大减少了模型的推理和多余的客套话(“Certainly! Here is…” 也是要算 Token 的)。 ...

2026-07-15 02:39:13 PM · 1 分钟

Flutter 相关面试题整理 更新中 

从互联网整理而来 一、Dart 基础 Dart 的数据类型有哪些? var、final、const 的区别 Dart 中 null safety 是什么,如何使用? late 关键字作用与使用场景 Dart 函数可选参数、命名参数、位置参数区别 箭头函数适用范围 Dart 异步:Future、async/await 原理 Stream 与 Future 区别,StreamController 使用 sync*、async*、yield、yield each 作用 Dart 类中 extends、implements、mixin 区别 mixin 有什么限制,能否构造函数传参 抽象类与接口区别 泛型 T、?T、T?、required T 区别 Dart 单例几种实现方式 工厂构造函数 factory 作用 常量构造函数使用条件 级联运算符 .. 原理 空值操作符 ?.、??、??= 用法 Dart 枚举进阶用法,能否自定义属性方法 Isolate 是什么,和线程区别,通信方式 Isolate 共享内存吗,数据传递限制 Zone 作用是什么 Dart 垃圾回收机制 函数一等公民体现在哪里 typedef 作用与场景 二、Flutter 框架核心原理 Flutter 三棵树:Widget、Element、RenderTree 关系 StatelessWidget 和 StatefulWidget 底层差异 State 生命周期完整流程 initState、didChangeDependencies、build、didUpdateWidget、dispose 执行时机 setState 底层更新机制 Widget 为什么是不可变的 immutable Element 作用,Element 复用逻辑 RenderObject 职责是什么 Key 的作用,几种 Key 区别(ValueKey、ObjectKey、UniqueKey、GlobalKey) GlobalKey 使用场景与隐患 LocalKey 解决什么问题 Widget 重建流程,哪些情况会触发重建 什么是 const Widget,好处是什么 Flutter 渲染流程:布局、绘制、合成步骤 布局约束流程:Constraints 传递规则 父布局约束如何限制子控件尺寸 RepaintBoundary 作用,何时使用 Layer 树作用,缓存机制 Flutter 与原生 Android/iOS 渲染区别 Skia 引擎作用 Impeller 渲染引擎对比 Skia 优势 Flutter 绘制原理,Canvas、Paint 流程 PipelineOwner 作用 WidgetsBinding、SchedulerBinding 职责 帧调度流程:Vsync、帧回调执行顺序 transientCallbacks、persistentCallbacks、postFrameCallbacks 区别 Flutter 热重载原理,热重启区别 编译模式:debug/profile/release 差异 AOT、JIT 编译区别 Flutter 页面路由底层实现原理 三、布局 & 基础组件 Row Column Flex 布局区别,主轴交叉轴概念 MainAxisAlignment、CrossAxisAlignment 所有枚举值含义 Expanded、Flexible 区别,flex 参数作用 Stack、Positioned 布局规则 Align、Center 底层关系 Padding、Container 内部结构 Container 嵌套过多有什么性能问题 SizedBox、ConstrainedBox、UnconstrainedBox 用途 AspectRatio、FittedBox 缩放逻辑 Wrap 自动换行实现原理 ListView 几种构造方式区别(默认、builder、separated) ListView.builder 高性能原理,复用机制 ListView 滚动复用失效场景 GridView 使用与性能优化 SingleChildScrollView 嵌套 ListView 报错解决方案 CustomScrollView、Sliver 体系是什么 SliverList、SliverGrid、SliverAppBar、SliverToBoxAdapter 使用场景 SliverPersistentHeader 固定吸顶实现 CustomScrollView 滚动统一原理 Table、DataTable 布局特性 IntrinsicHeight、IntrinsicWidth 性能损耗原因 LayoutBuilder 获取父布局约束场景 MediaQuery 获取设备信息,MediaQuery.of(context) 刷新机制 LayoutId、MultiChildLayout 自定义布局 Flow 高性能流式布局适用场景 四、状态管理 State 自身状态管理优缺点 InheritedWidget 底层原理,数据传递逻辑 InheritedModel 对比 InheritedWidget 优势 Provider 整套库实现原理(ChangeNotifierProvider、Consumer、Selector) Selector 为什么能精准局部刷新 ChangeNotifier 通知更新机制 StateProvider、FutureProvider、StreamProvider 区别 Riverpod 对比 Provider 改进点 Riverpod 全局状态、自动 dispose、无 context 优势 StateNotifier、AsyncNotifier 使用场景 Bloc 核心概念:Event、State、Bloc/Cubit Cubit 与 Bloc 区别 BlocProvider、BlocConsumer、BlocBuilder、BlocListener 分工 Bloc 状态单一数据源优势 GetX 状态管理原理,GetController 生命周期 GetX 全局路由、依赖注入实现 GetX 优缺点,存在什么性能隐患 Redux 在 Flutter 中使用逻辑 MobX 响应式原理,Observable、Action、Reaction 大型项目如何选型状态管理方案 跨页面共享状态几种实现方式对比 状态持久化配合状态管理怎么做 五、路由 & 导航 Navigator 1.0 路由栈管理原理 MaterialPageRoute、CupertinoPageRoute 区别 PageRouteBuilder 自定义转场动画 Navigator push/pop/pushReplacement/popUntil 逻辑 路由传参几种方式 Navigator 2.0 核心组件:Router、RouteInformationParser、RouterDelegate Navigator 2.0 完整路由流程 GoRouter 框架底层封装逻辑 GoRouter 嵌套路由、路由守卫、参数获取 路由栈持久化、页面状态保存方案 底部导航多 Tab 页面状态保持实现 路由拦截、登录鉴权统一处理 原生页面与 Flutter 页面互相跳转路由处理 页面返回监听 WillPopScope、PopScope 深度链接 deep link 适配方案 六、动画 Flutter 动画核心类:Animation、AnimationController、CurvedAnimation AnimationController vsync 作用,为什么需要 TickerProvider SingleTickerProviderStateMixin、TickerProviderStateMixin 区别 Tween、Animatable 差值计算原理 显式动画与隐式动画区别 AnimatedContainer、AnimatedOpacity 等隐式动画底层 Hero 共享元素动画实现原理 PageRoute 共享 Hero 流程 CustomAnimation 自定义动画组件 交错动画 Interval 使用 动画性能优化,避免重建 Lottie 动画集成原理,性能注意点 循环动画、反向动画实现 动画暂停、恢复、释放资源处理 自定义路由转场动画 七、网络 & 本地存储 dio 库封装思路,拦截器使用 dio 统一请求头、错误处理、token 自动刷新 取消请求 CancelToken 使用场景 并发请求、超时处理 Json 序列化反序列化几种方式(手动、json_serializable) fromJson/toJson 生成流程 Freezed 数据模型优势 http 库与 dio 对比 WebSocket 在 Flutter 中使用,重连机制 shared_preferences 底层存储原理 Hive 本地数据库优势,Box 使用 Hive 加密、大数据存储优化 sqflite 数据库操作,事务使用 Isolate 中操作数据库注意事项 文件读写 path_provider 获取路径 图片缓存 cached_network_image 实现逻辑 网络请求缓存策略设计 接口统一异常捕获封装方案 八、原生交互 MethodChannel MethodChannel、BasicMessageChannel、EventChannel 三者区别 MethodChannel 双向通信完整流程 Flutter 调用 Android 原生代码步骤 Flutter 调用 iOS OC/Swift 步骤 原生主动推送数据给 Flutter 使用哪个 Channel 传参类型限制,复杂对象传递方案 多页面 Channel 单例管理 PlatformView 嵌入原生 View(Android View、iOS UIView) PlatformView 性能问题与优化 原生页面跳转 Flutter 传参 权限通过原生通道申请方案 混合栈开发:flutterBoost 原理 flutterBoost 页面生命周期同步问题 原生资源与 Flutter 资源冲突处理 通信通道内存泄漏如何避免 九、性能优化专项 Widget 重建常见诱因与规避手段 const 构造优化原理 Key 不合理使用导致的性能问题 ListView 长列表优化方案 图片加载优化:尺寸、缓存、压缩 RepaintBoundary 拆分重绘区域场景 减少 Layer 树层级优化 避免使用 Intrinsic 系列控件原因 动画卡顿排查思路 DevTools 工具使用:性能面板、内存、Widget 检查 内存泄漏常见场景(Timer、Stream、Channel、Animation) 大图片、大量对象内存释放方案 Isolate 处理耗时计算优化 UI build 方法避免耗时操作 布局嵌套过深优化手段 页面 dispose 资源释放规范 Profile 模式性能排查要点 启动速度优化(包体积、懒加载、预加载) Flutter 包体积优化方案 滑动卡顿完整排查流程 十、图片、手势、输入、弹窗组件 Image 几种构造:AssetImage、NetworkImage、FileImage、MemoryImage ImageProvider 缓存机制 Image.network 缓存缺陷,cached_network_image 弥补方案 DecorationImage、FadeInImage 使用 GestureDetector 手势识别原理,多手势冲突 Listener 底层原始手势与 GestureDetector 区别 手势竞争、手势忽略场景 InkWell 水波纹实现原理,必须嵌套 Material TextField 控制器 TextEditingController 使用 TextField 输入监听、格式化、光标控制 表单 Form、GlobalKey 校验逻辑 ModalRoute、showDialog、showBottomSheet 弹窗原理 弹窗状态共享问题解决方案 Draggable、LongPressDraggable 拖拽实现 Transform 变换不改变布局约束特性 十一、项目工程 & 打包适配 pubspec.yaml 各字段含义,依赖版本约束 本地依赖、Git 依赖、远程依赖配置 pub 依赖冲突解决方法 Flutter 多环境配置(开发/测试/生产) Flavor 多渠道打包 Android & iOS Android 打包 keystore 配置,iOS 证书配置 AndroidManifest、Info.plist 权限适配 屏幕适配方案:媒体查询、比例、flutter_screenutil 深色模式适配实现 多语言国际化 intl 库使用 App 图标、启动页配置 Flutter 插件开发流程 平台区分代码编写(dart.io、Platform 判断) 混合开发项目目录结构 CI/CD 自动打包脚本思路 版本号管理升级方案 第三方插件兼容问题处理 十二、进阶底层 & 疑难场景 WidgetsApp、MaterialApp、CupertinoApp 内部结构 ThemeData 主题分发原理,局部主题覆盖 Navigator 上下文与页面上下文区别 context 获取上层 Widget 原理,BuildContext 分类 State 保存在 Element 中,Widget 重建 State 不销毁条件 Offstage、Visibility 控件隐藏区别 AbsorbPointer、IgnorePointer 拦截手势差异 Clip 裁剪控件:ClipRect、ClipRRect、ClipOval 性能 BackdropFilter 模糊控件性能损耗原因 RenderBox 自定义控件完整流程 自定义 RenderObject 实现步骤 自定义 MultiChildRenderObjectWidget ScrollController 监听滚动、滚动定位 ScrollPhysics 滚动回弹、阻尼自定义 监听应用前后台切换 AppLifecycleState 截屏、屏幕亮度、震动原生能力实现 WebView 插件使用与通信 Flutter Web 编译差异,平台兼容问题 Flutter Windows/macOS/Linux 桌面端适配要点 如何实现全局捕获异常 Timer、StreamSubscription 忘记取消的内存泄漏 列表 item 点击状态保存方案 异步并发竞态条件问题处理 图片大量加载 OOM 解决方案 原生弹窗遮挡 Flutter 页面问题 十三、综合项目面试问答题 讲一下你项目整体架构分层 项目状态管理选型原因 长列表卡顿怎么优化的 多页面共享登录状态如何实现 token 过期统一拦截处理方案 项目混合栈开发遇到哪些坑 图片缓存、网络缓存怎么设计 全局网络加载弹窗、错误页封装思路 项目通用业务组件封装思路 线上卡顿、崩溃排查处理经验 如何实现页面无网络重试逻辑 复杂表单页面状态管理方案 项目包体积优化做了哪些操作 多渠道、多环境配置实现 封装通用 Dio 请求库完整思路

2026-07-15 12:46:10 AM · 3 分钟

MyBatis 相关面试题整理 更新中 

Mybatis 执行流程 mybatis-config.xml (总规) ↓ SqlSessionFactory (总管) ↓ SqlSession (服务员) —— 包含所有执行方法 ↓ Executor (大管家) —— 优先查缓存(一级/二级) ↓ MappedStatement (菜谱) —— 持有SQL、参数映射、结果映射 ↓ 输入参数映射 (备菜) → JDBC执行 → 输出结果映射 (装盘) ↓ 返回POJO/集合 (上菜) Mybatis 是否支持延迟加载 支持,默认不开启 collection fecthType=“lazy” mybatis配置文件延迟加载 lazyLoadingEnabled 延迟加载的原理 CGLIB创建目标对象的代理对象 调用目标方法 getOrderList 调用对象 invoke 方法 判断 orderList 是否为空 为空,执行SQL 不为空获取结果 封装 orderList Mybatis 的一级缓存 二级缓存 用过吗 本地缓存 - 基于 PerpetualCache 本质是一个 HashMap 一级缓存 - 作用域是 session 级别 二级缓存 - 作用域是namespace 和 mapper的作用域,不依赖于 session 二级缓存默认关闭 settings name=“cacheEnabled” value=“true” 当某个作用域进行了增删改操作,该作用域下的所有select的缓存将被clear

2026-07-15 12:46:10 AM · 1 分钟

React 相关面试题整理 更新中 

从互联网整理而来 一、JS 基础前置 原型与原型链 闭包、闭包引发的内存泄漏场景 同步异步、宏任务微任务执行顺序 Promise 状态、静态方法、链式调用 async/await 原理 深浅拷贝实现与区别 this 指向五种场景 箭头函数与普通函数差异 ES6 解构、展开运算符、剩余参数 var / let / const 区别 CommonJS 与 ES Module 差异 TypeScript 接口、泛型、交叉类型、联合类型 EventLoop 完整执行流程 防抖节流实现原理 纯函数定义与特性 二、React 基础核心概念 React 设计思想与核心理念 虚拟 DOM 是什么,作用与优势 JSX 语法本质,编译产物 JSX 中 {} 可放入哪些内容,不能放什么 React 元素与组件区别 函数组件与类组件区别 纯组件 PureComponent 原理 React 单向数据流含义 props 只读特性,为什么不能直接修改 props.children 有哪些类型 key 的作用,为什么不能用 index 做 key React 列表渲染注意事项 className 代替 class、htmlFor 代替 for 原因 React 事件绑定与原生 DOM 事件差异 合成事件原理、事件委托机制 阻止合成事件冒泡几种方式 dangerouslySetInnerHTML 使用场景与风险 React 为什么不直接操作 DOM Fragment 作用,短语法 <> React 严格模式 StrictMode 作用 三、类组件生命周期(Class Component) 类组件完整生命周期分哪三个阶段 constructor 执行时机与作用 static getDerivedStateFromProps 执行时机与用途 shouldComponentUpdate 返回值作用 render 执行规则,禁止在其中修改 state componentDidMount 执行时机、常用场景 getSnapshotBeforeUpdate 触发时机、返回值用途 componentDidUpdate 参数含义,依赖判断写法 componentWillUnmount 清理资源场景 废弃生命周期函数有哪些,为什么废弃 props 变化触发的生命周期流程 setState 同步还是异步,底层批量更新逻辑 setState 两种传参形式(对象/函数)区别 多次连续 setState 合并规则 如何在 setState 后拿到最新 state 四、Hooks 全套(React16.8+) Hook 诞生背景,解决类组件什么痛点 Hook 使用两条硬性规则 useState 底层原理,为何数组解构不受顺序影响 useState 传入函数初始化的优势 useEffect 作用,依赖数组含义 useEffect 模拟生命周期分别怎么写 useEffect 返回清理函数执行时机 依赖数组漏传变量引发的闭包陷阱 useLayoutEffect 和 useEffect 执行顺序、区别 useMemo 缓存计算值,解决什么问题 useCallback 缓存函数,搭配子组件使用场景 useMemo 与 useCallback 性能误区 useRef 存储DOM、存储可变数据两种用法 ref 传递 forwardRef 使用场景 useImperativeHandle 作用 useContext 跨层级传值,使用缺陷 useReducer 适用场景,和 useState 对比 useReducer 简单实现思路 useId 作用,解决什么问题 useTransition 区分紧急/非紧急更新 useDeferredValue 延迟计算值 useSyncExternalStore 订阅外部数据源 useDebugValue 自定义Hook调试展示 自定义 Hook 封装规范,复用逻辑思路 Hook 闭包陷阱完整成因与解决方案 五、React18 新特性 React18 并发渲染 Concurrent Mode 含义 自动批处理更新范围变化 createRoot 替换 legacy root 差异 Suspense 服务端/客户端用法 Transitions API 解决场景 自动插入批处理,异步回调内也合并更新 useTransition 与 useDeferredValue 区别 服务端组件 RSC 基础概念 StrictMode 双重渲染机制目的 批量更新边界,何时不会合并state更新 六、Diff 算法与渲染更新 React Diff 三大策略 同层比较,不跨层级对比原因 无key、index key、唯一key三种场景对比 节点删除、新增、移动判断逻辑 文本节点、组件节点 Diff 区别 列表 Diff 优化逻辑 什么情况下组件会重新渲染 如何避免不必要的重渲染 memo、useMemo、useCallback 配合使用完整逻辑 渲染流程:render → 生成VNode → Diff → 真实DOM更新 七、组件通信方案 父子组件 props 传值、回调传方法 多层级透传 props 缺点 Context API 跨层级通信优缺点 Context 配合 useReducer 简易状态管理 父访问子组件实例 ref 子调用父方法回调函数 兄弟组件通信几种方案 全局事件总线实现与缺陷 跨页面全局状态管理方案对比 八、状态管理 Redux / Redux Toolkit / Zustand Redux 三大核心原则 Redux 五大核心概念:Store、Action、Reducer、Dispatch、State Reducer 必须纯函数要求 Action plain object 规范,为什么不能异步 中间件 middleware 作用,执行流程 redux-thunk 异步处理原理 redux-saga 对比 thunk 优势 combineReducers 拆分模块原理 react-redux 核心 API Provider、connect mapStateToProps、mapDispatchToProps 作用 useSelector、useDispatch Hook 用法 Redux 数据单向流动完整流程 Redux Toolkit 解决原生Redux哪些痛点 createSlice 内置 reducer、action 生成 RTK 内置immer 实现可变写法原理 RTK Query 接口缓存、请求管理 Zustand 轻量状态库对比Redux优势 状态持久化 redux-persist 流程 大型项目状态库选型思路 多组件共享全局状态最佳实践 九、React Router v6 v5 与 v6 核心改动差异 createBrowserRouter 路由配置方式 BrowserRouter、HashRouter、MemoryRouter 区别 Routes 替代 Switch 作用 Route element 传组件写法 useNavigate 替代 useHistory 路由传参 params、search、state 三种方式 useParams、useSearchParams 使用 嵌套路由 Outlet 占位原理 index 索引路由作用 Link、NavLink 区别 路由守卫鉴权封装方案 路由懒加载 + Suspense 配置 useLocation 获取路由信息 动态路由、路由拦截封装 十、表单处理 受控组件与非受控组件定义、区别 受控组件完整实现思路 非受控组件通过 ref 获取值场景 多表单项统一封装受控逻辑 第三方表单库 Formik / React Hook Form 对比 React Hook Form 非受控高性能原理 表单校验方案:原生、yup、zod 表单批量重置、回填数据处理 十一、样式方案 inline 内联样式优缺点 CSS Modules 样式隔离原理 styled-components CSS-in-JS 原理 emotion 与 styled-components 对比 tailwindcss 在React项目使用优势 动态样式几种实现方式 全局样式污染解决方案 十二、工程化构建 Create React App 底层 webpack 配置 Vite 构建React项目优势,esbuild预构建 vite.config.js 常用配置项 webpack 处理jsx、ts-loader流程 babel 转换 JSX、polyfill 原理 .env 环境变量区分开发/测试/生产 跨域代理 proxy 配置 路由懒加载分包代码分割 Tree-Shaking 生效条件 打包体积优化手段 第三方组件库按需引入配置 unplugin-auto-import 自动导入hooks 十三、网络请求封装 axios 请求拦截、响应拦截封装 全局 loading、统一错误处理 token 过期无感刷新实现逻辑 重复请求取消方案 CancelToken 请求并发处理 封装自定义请求Hook SWR / React Query 数据请求缓存库原理 React Query 自动重请求、缓存失效策略 十四、性能优化专题 组件无效重渲染全部诱因 memo 缓存函数组件条件 useCallback 缓存函数使用场景 useMemo 缓存计算结果适用场景 列表渲染优化策略 虚拟列表 react-window / react-virtualized 原理 图片懒加载实现 路由懒加载分包优化首屏 大组件拆分、状态下沉优化 避免在render内创建函数/对象 React DevTools Profiler 排查卡顿 减少Context频繁更新范围 定时器、订阅事件组件卸载清理 打包体积压缩:gzip、剔除无用依赖 并发更新优化用户交互体验 十五、进阶底层原理 Fiber 架构解决旧架构什么问题 Fiber 节点结构、任务拆分机制 协调阶段、提交阶段分工 可中断、可恢复、可优先级调度原理 调和过程完整流程 批量更新实现机制 合成事件系统底层池化机制 React 事务机制 Portal 传送门实现原理,事件冒泡特点 ErrorBoundary 错误捕获范围,无法捕获哪些错误 React 服务端渲染 SSR 流程 Next.js 与 CRA 区别,SSR/SSG/ISR 概念 Hydrate 水合作用,水合不匹配成因 RSC React Server Components 运行机制 微前端中 React 应用隔离方案 十六、项目实战场景题 项目目录分层架构设计 状态管理选型理由 大型表单封装思路 页面按钮、接口权限控制实现 首屏加载缓慢优化方案 列表大量数据渲染卡顿解决 全局弹窗、消息提示封装 路由鉴权、未登录跳转逻辑 组件复用抽离自定义Hook规范 线上报错捕获监控方案 多环境变量、多渠道打包配置 防抖节流在搜索框场景实现 页面返回保留表单状态实现 重复提交接口拦截处理 React 项目迁移 TS 改造思路

2026-07-15 12:46:10 AM · 3 分钟