一個圖片采集的項目,每天會有差不多2-5G的文件上傳到服務器,項目初期直接把上傳的圖片存在服務器本地。
經過差不多3個月后發現購買的數據盤已經滿了,不得不重新擴容和添加數據盤,比較麻煩而且服務器帶寬不大,用戶查看圖片比較慢。
重新改了系統架構,把圖片存儲遷移到了阿里雲OSS。好處就是不用擔心數據盤不夠用,帶寬也足夠,只是費用高了一點。
雲服務器上的存儲路徑為:/data/日期/文件這種結構,遷移到Oss后基本路徑保持不變。
因為服務器上centos的,使用官方推薦的ossimport2進行遷移,ossimport2使用教程參考官方教程即可。
遷移完成之后,用戶需要進行對比一下看是否全部完成。對比試了兩種方案,
1.使用本地文件組合成object key一個一個去對比
這種方式比較慢,而且容易出現網絡錯誤,
// 創建OSSClient實例 OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); // Object是否存在 boolean found = ossClient.doesObjectExist("<bucketName>", "<key>")
2.把OSS服務器上的文件數據同步下來,在本地進行比較(推薦)
這種方式就是稍微麻煩,需要建立一個數據庫來存儲同步下來的數據。
- 創建數據庫表
CREATE TABLE `dcs` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `path` varchar(255) DEFAULT NULL, `dates` varchar(10) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
- 編寫數據庫操作代碼
<dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.sql2o</groupId> <artifactId>sql2o</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.29</version> </dependency>
public class DbUtils { private static Sql2o SQL = new Sql2o("jdbc:mysql://127.0.0.1:3306/oss", "root", "root");; public static void bachInsert(List<OSSObjectSummary> sums) { String insertSql = "insert into dcs(path,dates) values (:path,:dates)"; try (Connection con = SQL.beginTransaction()) { Query query = con.createQuery(insertSql); for (OSSObjectSummary s : sums) { String path = s.getKey(); if (path.length() < 20){ System.out.println(path); continue; } query.addParameter("dates",path.substring(11, 19)); query.addParameter("path", path.substring(20)).addToBatch(); } query.executeBatch(); // executes entire batch con.commit(); } } }
- 編寫同步代碼
public class OssSynchClient { // log private static final Logger LOG = LoggerFactory.getLogger(OssSynchClient.class); // 阿里雲API的內或外網域名 private static String ENDPOINT = "<ENDPOINT>"; // 阿里雲API的密鑰Access Key ID private static String ACCESS_KEY_ID = "<ACCESS_KEY_ID>"; // 阿里雲API的密鑰Access Key Secret private static String ACCESS_KEY_SECRET = "<ACCESS_KEY_SECRET>"; private static String BUCKET_NAME = "<BUCKET_NAME>"; private OSSClient client; public OssSynchClient() { client = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET); } public void synchFromOssServer() { final int maxKeys = 200; final String keyPrefix = "<keyPrefix>"; String nextMarker = null; ObjectListing objectListing; do { objectListing = client.listObjects(new ListObjectsRequest(BUCKET_NAME).withPrefix(keyPrefix) .withMarker(nextMarker).withMaxKeys(maxKeys)); List<OSSObjectSummary> sums = objectListing.getObjectSummaries(); DbUtils.bachInsert(sums); nextMarker = objectListing.getNextMarker(); } while (objectListing.isTruncated()); } public static void main(String[] args) { OssSynchClient osc = new OssSynchClient(); osc.synchFromOssServer(); } }
- 數據庫對比
###dcs為同步下來的數據
###pic_mdf 為本地服務器數據
SELECT p.md,p.path FROM pic_mdf p WHERE NOT EXISTS(SELECT 1 FROM dcs d WHERE d.path = p.md)
由此可以過濾出沒有同步到OSS的圖片,然后調用oss上傳api單獨處理下即可。