SyncDataFacade 使用手册
2026年3月6日大约 5 分钟
SyncDataFacade 使用手册
版本: v1
作者: youhujun & xueer
更新日期: 2026-03-04
📖 概述
SyncDataFacade 是游鹄生态中用于同步数据到映射表的专用门面服务。它负责将主表的数据同步到对应的映射表中,以支持跨服务的数据查询和路由。
核心特点
- ✅ 自动创建/更新映射表:根据业务ID自动查询或创建映射表记录
- ✅ 分片路由支持:自动根据分片信息路由到正确的映射表分片
- ✅ 模型映射管理:通过
modelMap管理不同模型映射表的同步逻辑 - ✅ 事件驱动:同步完成后自动触发事件通知
- ✅ 日志记录:自动记录同步操作日志
适用场景
- 微服务架构下同步数据到映射表
- 用户注册后同步用户映射信息
- 数据变更后更新映射表
- 跨服务数据查询前的数据同步
🔄 工作原理
映射表同步流程
业务操作(如用户注册)
↓
1. 调用 SyncDataFacade::syncMapData()
↓
2. 解析 SyncMapDTO 获取参数
- user_uid: 业务ID
- shardInfo: 分片信息
- modelData: 需要同步的模型数据
↓
3. 根据 base_table 查找对应的处理器
↓
4. 执行同步逻辑
- 查询映射表是否存在
- 不存在:创建新记录
- 存在:更新现有记录
↓
5. 触发事件通知
↓
6. 返回同步结果模型映射配置
SyncDataFacadeService 中通过 $modelMap 管理模型映射:
private $modelMap = [
'users' => [
'code' => 10,
'handler' => function ($bizId, $shardInfo, $modelData) {
// 同步逻辑
}
],
// 'orders' => [...],
// 'products' => [...],
];📚 方法详解
syncMapData
同步映射数据到映射表。
方法签名
public function syncMapData(SyncMapDTO $syncMapDTO): mixed参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
$syncMapDTO | SyncMapDTO | 是 | 同步映射数据传输对象 |
SyncMapDTO 字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
user_uid | string | 是 | 业务ID(如用户UID) |
shardInfo | string | 是 | 分片信息(JSON字符串) |
modelData | string | 是 | 模型数据(JSON字符串) |
shardInfo 结构
{
"biz_id": "276406781286953",
"shard_db": "ds_0",
"shard_table": "users_0",
"shard_key": 0,
"base_table": "users"
}modelData 结构
{
"account_name": "develop",
"phone": "13800138000",
"email": "user@example.com",
"nick_name": "测试用户"
}返回值
成功时返回:
[
'code' => 0,
'msg' => '同步users成功'
]失败时抛出 CommonException 异常。
异常处理
| 异常 | 说明 |
|---|---|
BaseModelEmptyError | 基础模型未配置 |
ModelCodeEmptyError | 模型编码无效 |
AddUserMapError | 添加映射表记录失败 |
AddUserMapWithUpateError | 添加映射表记录后更新失败 |
UpdateUserMapError | 更新映射表记录失败 |
💡 使用示例
示例1:用户注册后同步映射数据
use App\Facades\LaravelShardMap\V1\Api\Map\SyncDataFacade;
use App\Facades\Common\V1\Shard\ShardHelperFacade;
use App\DTOs\Api\V1\Map\SyncMapDTO;
class UserRegisterService
{
/**
* 用户注册
*/
public function register(array $registerData)
{
// 1. 创建用户主表记录
$userUid = $this->generateUserUid();
$user = User::create([
'user_uid' => $userUid,
'account_name' => $registerData['account_name'],
'phone' => $registerData['phone'],
'password' => Hash::make($registerData['password']),
]);
// 2. 计算分片信息
$shardInfo = ShardHelperFacade::calc($userUid, 'user');
// 3. 准备映射表数据
$syncMapDTO = new SyncMapDTO();
$syncMapDTO->set('user_uid', $userUid);
$syncMapDTO->set('shardInfo', json_encode($shardInfo));
$syncMapDTO->set('modelData', json_encode([
'account_name' => $user->account_name,
'phone' => $user->phone,
'email' => $user->email ?? '',
'nick_name' => $user->nick_name ?? '',
]));
// 4. 同步到映射表
$syncResult = SyncDataFacade::syncMapData($syncMapDTO);
if ($syncResult['code'] !== 0) {
throw new BusinessException('同步映射表失败');
}
return $user;
}
}示例2:微服务间数据同步
use App\Facades\LaravelShardMap\V1\Api\Map\SyncDataFacade;
use App\DTOs\Api\V1\Map\SyncMapDTO;
class MapSyncController
{
/**
* 接收来自其他服务的映射数据同步请求
*/
public function syncMap(Request $request)
{
// 1. 验证并创建 DTO
$syncMapDTO = new SyncMapDTO();
$syncMapDTO->set('user_uid', $request->input('user_uid'));
$syncMapDTO->set('shardInfo', $request->input('shardInfo'));
$syncMapDTO->set('modelData', $request->input('modelData'));
// 2. 执行同步
try {
$result = SyncDataFacade::syncMapData($syncMapDTO);
return $this->success($result);
} catch (CommonException $e) {
return $this->error($e->getMessage());
}
}
}🔒 内部处理逻辑
同步处理流程
以 users 模型为例,内部处理逻辑如下:
'users' => [
'code' => 10,
'handler' => function ($bizId, $shardInfo, $modelData) {
// 1. 查询映射表是否存在
$userMapObj = ShardMapHelperFacade::queryByShardWithCache(
UserMap::class,
$bizId,
['user_uid' => $bizId]
)->first();
if (!$userMapObj) {
// 2. 不存在:创建新记录
$userMapObj = ShardMapHelperFacade::createWithShard(
UserMap::class,
$bizId,
[
'user_uid' => $bizId,
'shard_db' => $shardInfo['db'],
'shard_table' => $shardInfo['table'],
]
);
if (!$userMapObj) {
throw new CommonException('AddUserMapError');
}
// 3. 更新其余字段
foreach ($modelData as $key => $value) {
$userMapObj->{$key} = $value;
}
$updateResult = $userMapObj->save();
if (!$updateResult) {
throw new CommonException('AddUserMapWithUpateError');
}
$result = ['code' => 0, 'msg' => "同步{$shardInfo['base_table']}成功"];
} else {
// 4. 存在:更新现有记录
foreach ($modelData as $key => $value) {
$userMapObj->{$key} = $value;
}
$updateResult = $userMapObj->save();
if (!$updateResult) {
throw new CommonException('UpdateUserMapError');
}
$result = ['code' => 0, 'msg' => "同步{$shardInfo['base_table']}成功"];
}
return $result;
}
]事件触发
同步完成后会自动触发事件:
$eventData = [
'user_uid' => $userUid,
'shardInfo' => $shardInfo,
'modelData' => $modelData
];
$serviceFlag = 'shard-map';
$eventCode = 'SyncMapData';
CommonEvent::dispatch($eventData, $serviceFlag, $eventCode, true);⚠️ 注意事项
1. 模型必须配置
使用前必须确保 $modelMap 中配置了对应的模型映射:
// ✅ 正确:users 已配置
SyncDataFacade::syncMapData($syncMapDTO);
// ❌ 错误:orders 未配置会抛出异常
// 抛出异常: BaseModelEmptyError2. DTO 字段必须完整
SyncMapDTO 的三个字段都必须设置:
// ✅ 正确:所有字段都设置
$syncMapDTO->set('user_uid', $userUid);
$syncMapDTO->set('shardInfo', json_encode($shardInfo));
$syncMapDTO->set('modelData', json_encode($modelData));
// ❌ 错误:字段缺失会导致后续处理失败3. shardInfo 必须包含 base_table
shardInfo 中必须包含 base_table 字段,用于查找对应的处理器:
{
"base_table": "users", // 必须字段
"shard_db": "ds_0",
"shard_table": "users_0"
}4. JSON 字符串格式
shardInfo 和 modelData 必须是有效的 JSON 字符串:
// ✅ 正确
$syncMapDTO->set('shardInfo', json_encode($shardInfo));
// ❌ 错误
$syncMapDTO->set('shardInfo', $shardInfo); // 应该是 JSON 字符串🎯 最佳实践
1. 封装同步操作
建议在业务层封装同步操作:
class UserSyncService
{
public function syncUserMapping(string $userUid, User $user): bool
{
$shardInfo = ShardHelperFacade::calc($userUid, 'user');
$syncMapDTO = new SyncMapDTO();
$syncMapDTO->set('user_uid', $userUid);
$syncMapDTO->set('shardInfo', json_encode($shardInfo));
$syncMapDTO->set('modelData', json_encode([
'account_name' => $user->account_name,
'phone' => $user->phone,
'email' => $user->email ?? '',
'nick_name' => $user->nick_name ?? '',
]));
$result = SyncDataFacade::syncMapData($syncMapDTO);
return $result['code'] === 0;
}
}2. 统一异常处理
try {
$result = SyncDataFacade::syncMapData($syncMapDTO);
if ($result['code'] !== 0) {
throw new BusinessException($result['msg']);
}
return $result;
} catch (CommonException $e) {
plog([
'error' => $e->getMessage(),
'user_uid' => $syncMapDTO->get('user_uid'),
], 'SyncDataFacade', 'syncError');
throw new BusinessException('同步映射表失败');
}3. 日志监控
定期检查同步日志:
# 查看同步日志
tail -f storage/logs/custom/SyncDataFacadeService/$(date +%Y-%m-%d)/syncMapData.log📊 与其他门面的关系
业务层操作(用户注册/更新)
↓
SyncDataFacade (同步映射表)
↓
ShardMapHelperFacade (查询/创建映射表)
↓
UserMap (映射表模型)
↓
CommonEvent (触发事件通知)💬 总结
SyncDataFacade 是游鹄生态中映射表数据同步的核心组件,其核心价值在于:
- ✅ 自动化同步:自动判断创建或更新映射表记录
- ✅ 分片路由:自动根据分片信息路由到正确的映射表分片
- ✅ 模型映射:通过
modelMap统一管理不同模型的同步逻辑 - ✅ 事件驱动:同步完成后自动触发事件通知
- ✅ 日志追踪:完整的同步操作日志记录
在实际开发中,建议在业务层封装同步操作,以获得更好的代码组织和可维护性。
© 2026 youhujun & xueer. All rights reserved.
