Java 里的“锁”,本质是把并发访问变成可控的串行或有序并行,手段大致分两大类:语言级内置监视器(monitor)与 java.util.concurrent(JUC)提供的显式锁与同步器。工程里常见的锁方式可以按“用法形态”和“能力特征”梳理。 语言级锁:synchronized(内置监视器锁)...
在 Linux 里查看文件末尾 100 行,最常用的是 tail: tail -n 100 文件名 tail:输出文件末尾内容 -n 100:指定输出 100 行(等价写法:tail -100 文件名) 常见变体: 实时追踪末尾日志(滚动输出新增内容): tail -n 100 -f 文件名
在二维数组里找指定值,关键先看二维数组是否带有“可利用的有序性”。不同前提,对应不同查找路径与复杂度。 无序二维数组:顺序遍历(最稳妥) 二维数组只是一块数据网格,没有行、列的排序保证时,唯一通用办法是把每个元素都看一遍。 做法:双重循环逐行(或逐列)扫描,遇到目标值立即返回。 复杂度:最坏需要检查...
雪花算法(Snowflake)做的事很朴素:把“时间”“机器”“序号”拼进一个固定宽度的整数里,用位运算快速生成全局唯一、趋势递增、可分片的 ID。生成过程不依赖中心数据库自增,也不需要分布式锁,适合高并发写入场景。 核心拼装思路:把一个 64 位整数切成几段 经典 Snowflake 使用 64 ...
高并发架构的本质不是“堆机器”,而是把一次用户请求拆成更短的临界区、更少的共享资源、更可控的状态,并把不可避免的慢路径(IO、外部依赖、写入一致性)从主链路上移走。50 万 QPS 更像一场系统性工程:入口削峰、读写分离、状态外置、异步化、分区化、以及全链路可观测与容量治理缺一不可。 1) 先把 5...
UUID(常见为 128 bit)在做 Base64 编码后,长度本质由两件事决定:输入字节数与 Base64 的分组填充规则。UUID 最常见有两种“输入形态”:原始 16 字节与文本形式(36 字符),两者编码后的长度差异很大。 Base64 长度的通用计算规则 Base64 把输入按 3 字节...
电商“超卖”的本质是:多个并发请求在同一时间窗口内读到“库存足够”,随后各自扣减并成功落单,最终扣减次数超过真实库存。解决思路只有两类:把“读库存 + 校验 + 扣减”合并成一个不可分割的原子操作;或把并发入口串行化。Redis 适合做前一类的高并发原子扣减与快速失败,CAS(Compare-And...
不同 embedding(嵌入)模型的“大小”一般有三种口径,必须先把口径对齐,否则数字没有可比性: 三种常用口径:参数量、向量维度、模型文件体积 参数量(Parameters) 典型指神经网络权重规模(如 100M、1B 参数)。它决定了推理成本与潜在表达能力上限。多数商用 API 不公开这一项,...
把 QPS 拉到 10 万,本质是把系统从“单机效率问题”升级为“端到端容量工程”。改造重点通常不在某一个点,而是沿着请求链路把短板逐段打穿:入口承载、业务计算、数据读写、异步化、隔离与稳定性、发布与可观测。以下按改造优先级展开。 容量目标与口径先定清 10 万 QPS 不是一个抽象数字,需要拆成可...
消息队列选型的核心差异不在“能不能发消息”,而在三件事:消息模型(偏流式还是偏队列)、投递语义(至少一次/至多一次/恰好一次)、以及系统侧重点(吞吐、时延、可运维性、生态与云服务成熟度)。Kafka、RabbitMQ、RocketMQ 分别把筹码押在不同方向上。 消息模型与定位:流平台 vs 传统队...