서론
어제 주기적인 패치때문에 데이터 동기화가 필요하기 때문에 작업의 필요성을 느끼고, 적용 되었다!
간단하게 작업 내용을 정리해 보려고 한당..
실 서버에 스케줄링 등록
protected function schedule(Schedule $schedule): void
{
$today = date("Y-m-d");
// 백업, 10분뒤 동기화 처리
$schedule->exec('mongodump -d arknights_info -o ~/dump/'.$today)
->dailyAt('0:00');
$schedule->job(function() {
$setDataController = new SetDataController();
$setDataController->setBuildingsSync();
$setDataController->setItemSync();
$setDataController->setOperatorKey();
$setDataController->setCharSync();
})->dailyAt('0:10');
// 백업된 DB 삭제 처리
$schedule->exec('find ~/dump -mtime +6 -delete')
->dailyAt('0:30');
}
스케줄링 부분의 코드는 다음과 같다.
맨 처음, 현 상태의 DB를 그대로 dump 시켜주고 나서 데이터 동기화를 실행한다.
이후에 오래된 백업 데이터를 삭제하는 명령어를 추가적으로 날려주어서, 서버 용량을 최적화 시켜준다.
서버에 배포 되고 나서 스케줄러를 적용하기 위해서는 crontab에 주기적으로 php artisan schedule:run 명령어를 입력해주도록 처리를 해야 한다.
crontab -e 명령어를 입력하여 다음과 같이 내용을 추가해 주었다.
* * * * * cd /home/ubuntu/arkinfo_server && php artisan schedule:run >> /home/ubuntu/cron/log/schedule.log
이후 service crontab start 명령어를 이용해서 crontab을 실행시켜주고,
프로젝트 폴더로 이동하여 스케줄러가 정상적으로 등록 되었는지 php artisan schedule:list 명령어로 확인해 주었다.
자동 배포시, DB migrate 추가
실패 로그를 쌓기 위하여 새로운 테이블을 추가한 부분도 있고, 큐를 이용하기 위해서도 새 테이블을 추가 해야만 했다.
자동배포시, 데이터베이스 마이그레이션 부분이 배제 되어 있어 해당 부분을 추가해 주었다.
기존 tasks 파일을 확인하여 아래 내용을 추가!
- name : db migrate
become: yes
shell: "cd {{server_dir}} && php artisan migrate --force"
실제로 여러 서버를 구동하고 있다면,
Ansible 서버에서 대상 타겟이 가장 주된 타겟 한쪽으로만 지정하여 migrate를 시켜주는 새로운 tasks를 만들어 주면 된다.
현재는 하나의 서버만 구동되고 있기 때문에, 대상이 하나밖에 없어서 그냥 추가 해 두었다.
데이터 싱크 일부 로직과, 결과 확인
일단, 현재 개발된 부분까지의 데이터 동기화가 완료되어 동기화 시켜본 결과 정상적으로 구동 되었고, 이미지들도 알아서 S3에 잘 올라간 것을 확인 하였다.
다음은 동기화 로직의 일부.
// 아이템 데이터 + 아이템 이미지 동기화
public function setItemSync() {
$itemData = $this->curlController->getCURL("https://raw.githubusercontent.com/Kengxxiao/ArknightsGameData/master/ko_KR/gamedata/excel/item_table.json");
$itemData = $itemData['data'];
$itemData = json_decode($itemData, true);
$itemData = $itemData['items'];
$nowItemCount = Items::count();
// 전체 카운트 가져와서 비교하고, 수가 다르면 없는 데이터 찾아서 insert.
print_r(count($itemData));
if(count($itemData) > $nowItemCount) {
$diffArray = $itemData;
$allItemId = Items::select('itemId')->get();
foreach($allItemId as $item) {
if(isset($itemData[$item->itemId])) {
unset($diffArray[$item->itemId]);
}
}
// 이미지 처리
foreach($diffArray as $item) {
$data = $this->curlController->getCURL("https://raw.githubusercontent.com/Aceship/Arknight-Images/main/items/".$item['iconId'].".png");
$imageData = $data['data'];
$syncFailController = new SyncFailController();
if($data['code'] == '404') {
// 이미지 리소스 없음.
$syncFailController->appendFailSync('items','iconId',$item['iconId'],SyncFailController::UPLOAD_IMAGE_RESOURCE_NOT_FOUND);
} else {
$checkFile = Storage::disk('s3')->exists('/items/'.$item['iconId'].'.png');
if(!$checkFile) {
// 만약 없으면 S3에 업로드 한다.
try {
Storage::disk('s3')->put('/items/'.$item['iconId'].'png',$imageData);
} catch(Error $error) {
// 실패시 DB 입력 하고 패스
$syncFailController->appendFailSync('items','iconId',$item['iconId'],SyncFailController::UPLOAD_FAIL);
}
}
}
try {
Items::insert($item);
} catch(Error $error) {
$syncFailController->appendFailSync('items','itemId', $item['itemId'], SyncFailController::INSERT_FAIL);
}
}
return 'success';
} else {
return 'end';
}
}
아이템 부분을 동기화 하는 부분이다.
git상에 있는 데이터는 curl을 통해 가져왔고, 현재 데이터 베이스와 비교하여 등록되지 않은 데이터만 산출, 해당 데이터만 추가 해주도록 작업 하였다.
키값을 이용한 배열 재편집으로, 중복데이터 제거 부분의 시간복잡도는 On 으로 짰고,
이미지쪽은 필요한 이미지만 추가하도록 작성하였으며, 만약 업로드 실패나 리소스가 없는 경우에는 Code별로 구분하여 SyncFail 테이블에 insert 되도록 작업해 두었다.
(실제로 리소스가 없는경우가 꽤나 있긴 한데, 일반적으로 해당 이미지들은 잘 노출되지 않는 파트들이라서 굳이 별도 작업을 해주지 않아도 될 것 같다)
결과, 이미지쪽과 데이터쪽 전부 작업이 잘 되어서 동기화 되며 추가된 데이터가 깔끔하게 잘 구현된 모습.
실제로 외부 데이터와 동기화 시켜야 하는 파트는 많이 작업해 보았었는데, 따로 정리해 둔 것 같지 않아서 이번기회에 정리해 보았다.
해당 작업 할 때 마다 가장 고된건 역시, 외부데이터 분석인 것 같다 ㅠㅠ.. 실제로 코드짜는 시간보다는 데이터 분석쪽 시간이 훨씬 많이드는 작업이기도 하다..
'프로그래밍 일지 > 명빵' 카테고리의 다른 글
[개인프로젝트] 데이터 동기화 (0) | 2023.05.11 |
---|---|
[개인프로젝트] Redux->Mobx 전환 및 typescript로 변환 (0) | 2023.05.05 |
[개인프로젝트] 오퍼레이터 목록 검색 , infinite scroll, 상태관리 (0) | 2023.03.23 |
[개인프로젝트] EC2 Next.js App 배포 (Ubuntu + next.js + pm2 + nginx + Route53 + Ec2 LB) (0) | 2023.03.21 |
[개인프로젝트] EC2 Mysql, MongoDB Setting 및 data transper (0) | 2023.03.20 |