ElementUI使用v-if控制tab標籤顯示遇到的Duplicate keys detected: 'xxx' 資料主鍵key重複
FastDFS
目錄一、FastDFS概述
1. 常見的分散式檔案系統對比
-
HDFS(Hadoop Distributed File System)和GFS(Google File System)是通用的分散式檔案系統,它們的優點是開發體驗好;缺點是系統的複雜度較高,效能也一般,需要將一個檔案分割成n份儲存在不同的節點上
-
FastDFS是專用的分散式檔案系統,它的優點是複雜度低,效能較高,適合儲存圖片、小視訊等小檔案,因為FastDFS對檔案是不分割的,所以沒有檔案合併的開銷;缺點是開發體驗一般
2. FastDFS組成概述
-
主要組成
-
Tracker Server
Tracker Server作用:負載均衡和排程,管理Storage Server
Tracker Server可以叢集,實現高可用,策略為輪詢
-
Storage Server
Storage Server作用:檔案儲存
Storage Server叢集採用分組的方式,同組內的每臺伺服器是平等關係、資料同步,目的是實現資料備份,從而高可用,而不同組的伺服器之間是不通訊的
Storage Server會連線Tracker Server叢集中的所有節點,定時向它們傳送自身狀態
(剩餘空間,檔案同步情況,檔案上傳下載次數等資訊),方便Tracker Server排程
-
-
工作流程
-
Storage定時向Tracker上傳狀態資訊
-
當Client上傳連線請求到Tracker時,Tracker查詢可用的Storage向Client返回資訊(Storage的IP和埠)
-
上傳和下載(需要Client與Tracker連線)
-
上傳:Client直接向Storage傳送file content和metadata,Storage生成file_id並將檔案寫入磁碟,最後Storage向Client返回file_id(包含路徑資訊和檔名)
-
下載:Client直接向Storage傳送file_id(包含組名、路徑和檔名),Storage查詢檔案後將file_content返回給Client
file_id格式:
組名(Storage Server)/虛擬磁碟路徑(M00或M01)/資料兩級目錄(虛擬磁碟自行建立)/檔名
-
-
二、FastDFS使用方式
1. 啟動服務
-
啟動tracker(需要同時啟動tracker和storage)
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
-
啟動storage(需要同時啟動tracker和storage)
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
-
檢視所有執行的埠
netstat -ntlp
-
上傳檔案前關閉防火牆
systemctl stop firewalld.service
三、FastDFS API
1. 實現檔案上傳
-
示例Code
當Storage單機存在時,組名為group1;
上傳後的檔案在
/etc/fdfs
中的storage.conf
中store_path0
對應的路徑下data
中,data
資料夾下也叫虛擬磁碟路徑public class TestUpload { public static void main(String[] args) { try { // 載入配置檔案 ClientGlobal.initByProperties("config/fastdfs-client.properties"); // 建立tracker客戶端 TrackerClient trackerClient = new TrackerClient(); // 通過tracker客戶端獲取連線服務並返回 TrackerServer trackerServer = trackerClient.getConnection(); // 宣告storage服務 StorageServer storageServer = null; // 定義storage客戶端 StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer); // 定義檔案元資訊 NameValuePair[] array = new NameValuePair[1]; array[0] = new NameValuePair("filename", "img01.png"); // 檔案上傳成功後會返回fileId String fileId = storageClient1.upload_file1("D:\\upload\\img01.png", "png", array); System.out.println("fileId = " + fileId); // 關閉連線 trackerServer.close(); } catch (Exception e) { e.printStackTrace(); } } } /* fileId = group1/M00/00/00/wKjFgGJdii2AcVIHAAC0ta2HgOc915.png */
2. 實現檔案查詢
-
示例Code
public class TestQuery { public static void main(String[] args) { try { // 載入配置檔案 ClientGlobal.initByProperties("config/fastdfs-client.properties"); // 建立tracker客戶端 TrackerClient trackerClient = new TrackerClient(); // 通過tracker客戶端獲取連線服務並返回 TrackerServer trackerServer = trackerClient.getConnection(); // 宣告storage服務 StorageServer storageServer = null; // 定義storage客戶端 StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer); // 查詢檔案資訊 FileInfo fileInfo = storageClient1.query_file_info1("group1/M00/00/00/wKjFgGJdii2AcVIHAAC0ta2HgOc915.png"); if (fileInfo != null) { System.out.println("fileInfo" + fileInfo); } else { System.out.println("The file does not exist"); } // 關閉連線 trackerServer.close(); } catch (Exception e) { e.printStackTrace(); } } } /* fileInfosource_ip_addr = 192.168.197.128, file_size = 46261, create_timestamp = 2022-04-18 23:56:29, crc32 = -1383628569 */
3. 實現檔案下載
-
示例Code
public class TestDownload { public static void main(String[] args) { try { // 載入配置檔案 ClientGlobal.initByProperties("config/fastdfs-client.properties"); // 建立tracker客戶端 TrackerClient trackerClient = new TrackerClient(); // 通過tracker客戶端獲取連線服務並返回 TrackerServer trackerServer = trackerClient.getConnection(); // 宣告storage服務 StorageServer storageServer = null; // 定義storage客戶端 StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer); // 下載指定file_id的檔案,通過位元組輸出流寫入檔案 byte[] array = storageClient1.download_file1("group1/M00/00/00/wKjFgGJdii2AcVIHAAC0ta2HgOc915.png"); FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\upload\\testdownload01.png")); fileOutputStream.write(array); fileOutputStream.close(); System.out.println("succeed to download file"); // 關閉連線 trackerServer.close(); } catch (Exception e) { e.printStackTrace(); } } } /* succeed to download file */
四、圖片/視訊伺服器案例
-
主要流程
需要配置圖片伺服器:安裝fastdfs-nginx-module,配置nginx.conf
server { listen 81; server_name 192.168.197.128; location /group1/M00 { root /home/fastdfs/fdfs_storage/data; ngx_fastdfs_module; } }
瀏覽器訪問server_name與監聽的埠號,可檢視nginx歡迎頁面
瀏覽器訪問server_name與監聽的埠號+fileId,可檢視圖片/視訊伺服器上儲存的指定檔案
-
示例Code
將檔案上傳到web伺服器上,將web伺服器上儲存的檔案上傳到FastDFS
@Controller public class FileAction { @RequestMapping("upload") @ResponseBody public FileSystem upload(MultipartHttpServletRequest request) throws Exception { FileSystem fileSystem = new FileSystem(); /* 1. 將檔案上傳到web伺服器上 */ // 從頁面的請求中, 獲取上傳的檔案物件 MultipartFile file = request.getFile("fname"); // 獲取檔案的原始檔名,並獲取檔案的副檔名,將UUID作為新上傳檔案的檔名 String originalFilename = file.getOriginalFilename(); String fileTypeName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1); String newFileName = UUID.randomUUID().toString() + "." + fileTypeName; // 將路徑轉換成檔案 File toSaveFile = new File("D:/upload/" + newFileName); file.transferTo(toSaveFile); /* 2. 將檔案上傳到FastDFS */ // 載入配置檔案 ClientGlobal.initByProperties("config/fastdfs-client.properties"); // 建立tracker客戶端 TrackerClient trackerClient = new TrackerClient(); // 通過tracker客戶端獲取連線服務並返回 TrackerServer trackerServer = trackerClient.getConnection(); // 宣告storage服務 StorageServer storageServer = null; // 定義storage客戶端 StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer); // 定義檔案元資訊 NameValuePair[] array = new NameValuePair[1]; array[0] = new NameValuePair("filename", originalFilename); // 檔案上傳成功後會返回fileId String fileId = storageClient1.upload_file1(toSaveFile.getAbsolutePath(), fileTypeName, array); System.out.println("fileId = " + fileId); // 關閉連線 trackerServer.close(); // 封裝fileSystem物件 fileSystem.setFileId(fileId); fileSystem.setFileName(originalFilename); fileSystem.setFilePath(fileId); return fileSystem; } }