1. 程式人生 > 其它 >ElementUI使用v-if控制tab標籤顯示遇到的Duplicate keys detected: 'xxx' 資料主鍵key重複

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排程

  • 工作流程

    1. Storage定時向Tracker上傳狀態資訊

    2. 當Client上傳連線請求到Tracker時,Tracker查詢可用的Storage向Client返回資訊(Storage的IP和埠)

    3. 上傳和下載(需要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.confstore_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;
        }
    }