이미지 저장 공간이 계속 찼다. 디스크를 늘렸는데 두 달 만에 또 찼다. 늘리는 것으로는 끝나지 않는다는 것이 그때 드러났다.
Table of contents
Open Table of contents
상황 — 차는 속도를 쟀다
늘리기 전에 얼마나 빨리 차는지 봤다.
$ du -sh /data/upload/2014-*
1.2G /data/upload/2014-01
1.8G /data/upload/2014-02
2.4G /data/upload/2014-03
du -sh 로 월별 디렉터리를 재니 달마다 늘고 있었고 1월 대비 3월이 두 배였다.
지금 사용 5.4G / 전체 10G
이 속도면 5월에 찬다
디스크를 20G로 늘리면 9월에 찬다. 늘리는 것으로는 몇 달을 버는 것이었다.
이 숫자가 없으면 늘릴지 구조를 바꿀지 정할 근거가 없다. 몇 주밖에 못 버는 것이면 늘리는 것은 시간을 사는 것이 아니다. 재 보니 이번 경우가 그쪽이었다.
무엇이 차지하는지 봤다
파일 수와 크기를 나눠 셌다.
$ find /data/upload -type f | wc -l
184,221
$ find /data/upload -type f -size +1M | wc -l
41,882
find -size +1M 에 걸린 것이 4만 개였고 그것이 용량의 대부분이었다.
$ find /data/upload -type f -size +5M | head -3 | xargs -I{} identify {}
/data/upload/2014-03/a.jpg JPEG 4032x3024 ...
identify 로 크기를 보니 휴대전화로 찍은 4032x3024 원본이 그대로 올라오고 있었다. 화면에서는 800픽셀로 줄여서 보여 준다.
크기별로 세면 어디를 손댈지가 바로 보인다. 전체 용량만 보면 골고루 늘어난 것처럼 느껴지는데 실제로는 한 종류가 대부분이었다.
원본을 버릴지 물어봤다
줄여서 저장하기로 했다.
$img = imagecreatefromjpeg($src);
$w = imagesx($img); $h = imagesy($img);
if ($w > 1600) {
$nh = (int)($h * 1600 / $w);
$dst = imagecreatetruecolor(1600, $nh);
imagecopyresampled($dst, $img, 0,0,0,0, 1600,$nh, $w,$h);
imagejpeg($dst, $target, 85);
}
imagecopyresampled 로 1600픽셀까지 줄였다. 화면에서 쓰는 800보다 크게 잡은 것은 나중에 더 큰 화면이 나올 수 있어서였다.
원본 평균 2.8MB → 줄인 뒤 평균 320KB
줄이면 원본이 없어지므로 그래도 되는지 물어봤다. 인쇄용으로 원본이 필요한 경우가 있다는 답이 와서 종류를 나눴다.
상품 이미지 원본 보관 (인쇄용)
게시글 첨부 줄여서 저장
프로필 사진 줄여서 저장
전부 줄이려던 것을 바꿨다. 물어보지 않았으면 필요한 것을 버렸다. 방법은 내가 정하고 무엇을 버릴지는 물어보는 것이 이 구분이었다.
이미 있는 것과 오래된 것
18만 개가 이미 있었다. 한 번에 줄이면 오래 걸리고 그동안 서비스가 느려진다.
// 하루 5천 개씩
$rows = $db->select("SELECT * FROM attach WHERE resized='N' AND type IN ('BOARD','PROFILE') LIMIT 5000");
foreach ($rows as $r) {
if (resize($r['path'])) {
$db->update('attach', $r['no'], ['resized' => 'Y']);
}
}
attach 의 resized 를 표시해 두고 밤에 조금씩 돌게 했다. 하루 5천 개면 한 달에 끝난다.
줄이기 전에 백업도 뒀다. 줄이는 코드에 문제가 있으면 되돌려야 한다.
$ rsync -a /data/upload/ /backup/upload-before-resize/
오래된 것은 얼마나 있는지부터 봤다.
SELECT YEAR(reg_date), COUNT(*), SUM(size)/1024/1024 AS mb
FROM attach GROUP BY YEAR(reg_date);
2011 12,041 1,840 MB
2012 28,442 2,910 MB
2013 61,220 4,120 MB
2014 82,518 3,880 MB
SUM(size) 로 연도별로 세니 2011~2012년 것이 4.7G였다. 그중 얼마나 읽히는지 봤다.
$ find /data/upload/2011* -type f -atime -90 | wc -l
41
1만 2천 개 중 90일 안에 읽힌 것이 41개였다. 다만 atime 은 relatime 이 기본이라 자주 갱신되지 않으므로 읽힌 적이 있다는 것 정도만 믿고 접근 로그를 같이 봤다.
거의 안 읽히는 것은 지우지 않고 다른 자리로 옮겼다. 다시 찰 때를 알게 하는 것도 넣었다.
#!/bin/sh
use=$(df /data | awk 'NR==2 {gsub("%","",$5); print $5}')
grow=$(du -sm /data/upload/$(date +%Y-%m) | cut -f1)
echo "$(date +%F) 사용률 ${use}% 이번달 ${grow}MB" >> /var/log/disk-trend
[ "$use" -gt 75 ] && echo "디스크 ${use}%" | mail -s "경고" ...
df 의 사용률만 보면 언제 찰지 모른다. 이번 달에 얼마나 늘었는지를 같이 남겨야 언제 다시 찰지가 갈린다.
정리
- 차면 늘리기 전에
du로 얼마나 빨리 차는지 잰다 - 늘리는 것이 몇 달을 버는 일인지 계산한다
find -size로 무엇이 차지하는지 크기별로 센다- 전체 용량만 보면 골고루 는 것처럼 보인다
- 줄여서 저장하되 원본이 필요한 종류를 물어본다
- 방법은 내가 정하고 무엇을 버릴지는 물어본다
- 이미 있는 것은 나눠서 처리하고 처리 전에 백업을 둔다
- 오래된 것이 얼마나 읽히는지 본다. 안 읽혀도 지우지 않고 옮긴다
atime은relatime탓에 자주 갱신되지 않으니 접근 로그를 같이 본다- 사용률만이 아니라 늘어나는 속도를 남긴다