一个图片采集的项目,每天会有差不多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单独处理下即可。