本文目录导读:

在 Laravel 分片选择中,推荐优先使用一致性哈希,以下是具体对比和分析:
取模分片 vs 一致性哈希
取模分片(Mod)
$shard = $userId % $totalShards;
- 优点:实现简单、计算快
- 缺点:扩展/缩容时数据迁移量大(几乎所有数据都需要重新分配)
一致性哈希(Consistent Hashing)
// 使用 Laravel 自带的一致性哈希实现
$shard = app('hash')->getShard($userId, $shards);
- 优点:扩展/缩容仅影响相邻节点,数据迁移量小(约 1/N 的数据)
- 缺点:实现稍复杂,需要处理虚拟节点
实际案例对比
假设从 4 个分片扩展到 5 个分片:
| 用户ID | 取模(4) | 取模(5) | 是否迁移 |
|---|---|---|---|
| 1 | 1 | 1 | |
| 2 | 2 | 2 | |
| 3 | 3 | 3 | |
| 4 | 0 | 4 | |
| 5 | 1 | 0 | |
| 6 | 2 | 1 | |
| 7 | 3 | 2 | |
| 8 | 0 | 3 |
- 取模:80% 数据需要迁移
- 一致性哈希:仅约 20% 数据需要迁移
Laravel 实现方案
使用 Laravel 自带 Hash
use Illuminate\Support\Facades\Hash;
class ShardManager
{
protected $shards = ['shard1', 'shard2', 'shard3', 'shard4'];
public function getShard($key)
{
return $this->shards[crc32($key) % count($this->shards)];
}
// 一致性哈希
public function getConsistentShard($key)
{
return app('hash')->getShard($key, $this->shards);
}
}
自定义一致性哈希实现
class ConsistentHash
{
private $nodes = [];
private $virtualNodes = 64;
public function addNode($node)
{
for ($i = 0; $i < $this->virtualNodes; $i++) {
$hash = crc32($node . '_vnode_' . $i);
$this->nodes[$hash] = $node;
}
ksort($this->nodes);
}
public function getNode($key)
{
if (empty($this->nodes)) {
return null;
}
$hash = crc32($key);
$nodes = $this->nodes;
foreach ($nodes as $nodeHash => $node) {
if ($nodeHash >= $hash) {
return $node;
}
}
return reset($nodes);
}
public function removeNode($node)
{
foreach ($this->nodes as $hash => $n) {
if ($n === $node) {
unset($this->nodes[$hash]);
}
}
}
}
数据库分片示例
class ShardedUser extends Model
{
protected $connection = 'mysql';
protected $table = 'users';
public function getConnection()
{
$shardId = $this->getShardId();
return config("database.connections.shard_{$shardId}");
}
private function getShardId()
{
// 使用一致性哈希确定分片
$hash = app('hash')->getShard($this->id, range(0, 3));
return $hash;
}
}
选择建议
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 分片数固定且不会扩缩容 | 取模 | 简单高效 |
| 未来可能扩展/缩容 | 一致性哈希 | 数据迁移最小化 |
| 数据分布需要尽可能均匀 | 一致性哈希(多虚拟节点) | 更好的均匀性 |
| 高并发场景 | 取模 | 计算开销小 |
| 需要考虑热点问题 | 一致性哈希 + 虚拟节点 | 分散热点 |
注意事项
- 虚拟节点数量:一般建议 64-256 个,数据分布更均匀
- 数据迁移策略:扩缩容时需实现数据迁移逻辑
- 一致性要求:分片键选择要保证数据一致性
- 监控:监控各分片负载,及时调整
除非确定永远不会扩缩容,否则推荐一致性哈希,它在扩展性、数据分布均匀性和运维复杂度之间取得了更好的平衡。