https://mp.weixin.qq.com/s/FGjppy6yTLdCKD7oQQpXWA



技术选型
这次研究让我明白了,技术选型必须结合具体业务场景。阿里为了应对超大规模、高并发、高可用的场景,重写 HashMap 并做了这些优化:
阿里的业务特点:
超大规模:单机存储亿级数据
高并发:双11期间 QPS 百万级
低延迟:99.9% 请求要求 <10ms
高可用:不能因为扩容影响服务
JDK ConcurrentHashMap 的局限性:
扩容时全量 rehash,影响响应时间
内存布局不够紧凑,浪费空间
分段锁粒度不够细,高并发下仍有瓶颈
public class OptimizedCache<K, V> {
private final Map<K, V> hotData;
private final Map<K, V> coldData;
public OptimizedCache(int hotSize, int coldSize) {
this.hotData = new ConcurrentHashMap<>(hotSize, 0.9f);
this.coldData = new ConcurrentHashMap<>(coldSize, 0.75f);
}
public V get(K key) {
V value = hotData.get(key);
if (value != null) return value;
value = coldData.get(key);
if (value != null) {
promoteToHot(key, value);
}
return value;
}
}
带着疑问,我开始研究阿里的开源项目,发现了几个有趣的优化方案:
- 分段锁的进化版
阿里内部对 HashMap 进行了分段锁优化,每个段独立扩容,避免全局锁的瓶颈:
public class SegmentedHashMap<K, V> {
private final Segment<K, V>[] segments;
private final int segmentMask;
public V put(K key, V value) {
int hash = hash(key);
int segIndex = (hash >>> 28) & segmentMask;
return segments[segIndex].put(key, value, hash);
}
static class Segment<K, V> {
private volatile HashEntry<K, V>[] table;
// ...
}
}
- 内存预分配策略
基于业务特点,阿里还进行了内存预分配,避免了频繁的扩容和对象创建:
public class PreSizedConcurrentMap<K, V> extends ConcurrentHashMap<K, V> {
public PreSizedConcurrentMap(int expectedSize, float loadFactor) {
super(calculateInitialCapacity(expectedSize, loadFactor), loadFactor);
}
private static int calculateInitialCapacity(int expected, float lf) {
return (int) Math.ceil(expected / lf);
}
}文档更新时间: 2025-11-27 21:13 作者:admin