1 điểm bởi GN⁺ 2024-10-31 | 1 bình luận | Chia sẻ qua WhatsApp
  • Fast Dedup trong OpenZFS 2.3.0 đã cải thiện đáng kể so với dedup cũ, nhưng vẫn là tính năng mà người dùng phổ thông cần cân nhắc chi phí và điều kiện trước khi bật như một mặc định
  • dedup hoạt động bằng cách không ghi lại các block đã được lưu, mà chỉ tăng tham chiếu, nên mọi đường ghi và giải phóng đều phải chịu chi phí tra cứu và cập nhật dedup table
  • Cách cũ gây gánh nặng lớn về bộ nhớ và IO do khuếch đại read-modify-write của bảng dựa trên ZAP, live entry list không thể thu hồi trong thời gian transaction, và các unique entry không mang lại lợi ích
  • Fast Dedup giảm live entry từ 424 byte xuống 216 byte, đồng thời cung cấp dedup log, flush tăng dần, zpool ddtprune, dedup_table_quota, DDT prefetch và kstats để người vận hành kiểm soát chi phí tốt hơn
  • Với workload thông thường, số block thực sự trùng lặp có thể ít, và BRT/block cloning của OpenZFS 2.2 có thể đem lại mức tiết kiệm tương tự với chi phí thấp hơn, nên dedup chỉ đáng dùng một cách thận trọng khi vừa có lượng dữ liệu trùng lặp lớn vừa không có lựa chọn zero-copy thay thế

Cơ chế hoạt động cơ bản của OpenZFS dedup

  • Khử trùng lặp (dedup) là tính năng cho phép OpenZFS, trước khi ghi dữ liệu xuống đĩa, bỏ qua lần ghi mới nếu cùng dữ liệu đã tồn tại và thêm tham chiếu vào bản sao hiện có
  • Phần khó là phải liên tục lưu trữ và tra cứu thông tin để nhanh chóng biết “dữ liệu đã có trên đĩa chưa” và “nằm ở đâu”
  • Cấu trúc chứa thông tin này là dedup table
    • Về mặt khái niệm, đây là một bảng băm dùng checksum của dữ liệu làm khóa, còn vị trí trên đĩa và số tham chiếu (refcount) làm giá trị
    • Đây không phải dữ liệu người dùng, mà là dữ liệu pool mang tính cấu trúc, được lưu như một phần của pool metadata

Chi phí gắn vào đường ghi và giải phóng

  • Khi dedup tắt, OpenZFS nhận cấp phát không gian từ metaslab allocator, đưa DVA được trả về vào block pointer rồi ghi dữ liệu
  • Khi dedup bật, trước tiên checksum được tra trong dedup table
    • Nếu không có entry, hệ thống cấp phát không gian mới, ghi dữ liệu, rồi tạo dedup entry mới với refcount bằng 1
    • Nếu có entry, hệ thống sao chép DVA hiện có vào block pointer, đánh dấu IO ghi là hoàn tất, rồi tăng refcount
  • Với block được cấp phát bằng dedup, cờ D được đặt trong block pointer
    • Khi giải phóng, nếu có cờ D, hệ thống tra lại dedup table và giảm refcount
    • Khi refcount về 0, dedup entry bị xóa và không gian thật sự được giải phóng
  • Vì mọi lần ghi và giải phóng đều đi qua tra cứu/cập nhật dedup table, để dedup hữu ích thì mức tiết kiệm không gian/IO thực tế phải lớn hơn overhead quản lý bảng

Vì sao dedup cũ tệ

  • Khuếch đại của dedup table dựa trên ZAP

    • Dedup table cũ dùng ZAP, đối tượng bảng băm on-disk tiêu chuẩn của OpenZFS
    • ZAP là cấu trúc đa dụng được dùng cho thư mục, danh sách thuộc tính và quản lý nội bộ, nhưng không thật phù hợp để lưu dedup entry
    • Một dedup entry điển hình gồm khóa 40 byte và giá trị khoảng 64 byte sau nén; một ZAP block 32K chứa khoảng 188 entry thông thường
    • Vì OpenZFS không ghi một phần block và không ghi đè tại chỗ, chỉ cần cập nhật một entry cũng phải đọc toàn bộ ZAP block, sửa đổi rồi ghi lại thành block mới
    • Khóa checksum phải có khả năng chống va chạm mạnh, nên khả năng hai entry bất kỳ được đặt gần nhau trong cùng một ZAP block là thấp, và khả năng nhiều cập nhật trong một transaction gom vào cùng block cũng thấp
    • Nếu RAM đủ lớn để ARC giữ dedup table liên tục, chi phí đọc sẽ giảm; đây cũng là nguồn gốc của khuyến nghị lâu nay rằng dedup cần nhiều bộ nhớ
    • dedup vdev class có thể thêm dedicated dedup vdev đủ lớn và đủ nhanh để giảm phần nào nhu cầu bộ nhớ, nhưng ở quy mô mà dedup có ý nghĩa, thiết bị này cần đủ dung lượng chứa toàn bộ bảng và đủ tốc độ
  • Mức dùng bộ nhớ của live entry list

    • Trong OpenZFS, các dedup entry được tạo hoặc sửa trong transaction được giữ trong live entry list trong bộ nhớ
    • Đây là cấu trúc để tránh tình huống cùng một dữ liệu được ghi nhiều lần cùng lúc, mỗi write thread đều nghĩ rằng dedup table chưa có dữ liệu đó và tất cả đều ghi mới
    • Lookup trước tiên kiểm tra live entry list
      • Nếu có entry tương ứng, refcount được tăng
      • Nếu không có, hệ thống tạo live entry ở trạng thái “in progress”, đọc entry thực từ ZAP rồi chuyển sang “ready”
      • Các write thread khác truy cập đồng thời sẽ chờ cho đến khi entry ready
    • Khi transaction kết thúc, hệ thống duyệt live entry list và phản ánh nội dung liên quan vào dedup ZAP
    • Live entry cũ chiếm 424 byte mỗi entry, và bộ nhớ này không thuộc ARC mà là kernel slab memory, nên không thể thu hồi khi hệ thống bị áp lực bộ nhớ
    • Live entry list được làm trống sau mỗi transaction, nhưng nếu một transaction ghi nhiều dữ liệu khác nhau thì mức peak sẽ lớn
  • Unique entry làm bảng phình to

    • Dedup theo dõi mọi block được lưu trên đĩa, nhưng lợi ích thực tế chỉ xuất hiện khi refcount lớn hơn 1
    • Unique entry có refcount bằng 1 gần như là chi phí để chờ một ngày nào đó cùng dữ liệu được ghi lại
    • Dedup được thực hiện ở cấp block sau mã hóa và nén
    • Ngay cả với cùng dữ liệu gốc, block chỉ được coi là giống nhau khi phương thức nén, khóa mã hóa và cả căn chỉnh trong file đều khớp
    • Với workload mục đích chung, số block “thật sự giống nhau” ít, nên chi phí dedup dễ vượt lợi ích

Các cải tiến của Fast Dedup

  • Thu nhỏ live entry

    • Fast Dedup trước hết giảm memory footprint của live entry list
    • Các cờ kiểu số lớn trong ddt_entry_t được đổi thành bitfield, và các trường đồng bộ hóa được đơn giản hóa
    • Trạng thái 40 byte chỉ dùng khi ghi lần đầu block dữ liệu đã dedup hoặc khi cần repair write được tách thành một đối tượng IO state riêng
    • Giá trị dedup entry cũ có kích thước 256 byte, bao gồm bốn physical entry
    • Mỗi physical entry chứa ba DVA 128 bit, refcount và birth transaction id
    • Entry thứ tư là di tích của tính năng dedupditto trước đây; OpenZFS hiện đại chỉ hỗ trợ đọc và không ghi mới
    • Khi copies= thay đổi và cần thêm DVA, Fast Dedup không giữ biến thể cũ như entry riêng, mà chỉ cấp phát các bản sao bổ sung cần thiết và thêm vào dedup entry hiện có
    • Giá trị entry của Fast Dedup table mới giảm từ 256 byte xuống 72 byte
    • Một entry trong live list giảm từ 424 byte xuống 216 byte
  • Giới thiệu dedup log

    • Cách cũ phản ánh live entry list trực tiếp vào dedup ZAP khi transaction kết thúc, gây chi phí cập nhật theo block ngay cả khi 187 mục xung quanh entry hầu hết không liên quan
    • Fast Dedup bổ sung dedup log dựa trên quan sát rằng các block mới được tạo hoặc vừa bị trùng lặp có khả năng tiếp tục bị trùng lặp hoặc được giải phóng cao hơn
    • Khi kết thúc transaction, các thay đổi của live entry không được ghi ngay vào ZAP mà được ghi vào log
      • on-disk log cần thiết để đảm bảo an toàn khi crash
      • in-memory log được duy trì để lookup nhanh
    • Thứ tự lookup trở thành live entry list, in-memory log, rồi dedup ZAP
    • on-disk log được dùng để khôi phục in-memory log khi import pool
  • Flush log tăng dần

    • Nếu flush toàn bộ log vào ZAP một lần khi log quá lớn như cách ban đầu, chỉ vài nghìn entry cũng có thể gây pause dài
    • Fast Dedup dùng incremental flushing, phản ánh một phần log vào ZAP trong mỗi transaction
    • Lượng flush được điều chỉnh bằng cách so với thời gian đã tiêu tốn cho IO thực tế
      • Khi bận thì ghi ít hơn, khi rảnh thì ghi nhiều hơn
      • Nếu in-memory log lớn lên và gây áp lực bộ nhớ, flush có thể được tăng tốc
    • Để giữ on-disk log theo kiểu append-only mà vẫn làm rỗng được mà không phải dừng toàn bộ, hệ thống dùng hai log
      • Một log là active log nhận thay đổi mới
      • Log còn lại là flushing log được phản ánh vào ZAP
      • Khi flushing log rỗng, on-disk log được zero hóa và hai log đổi vai trò
    • Với pool scan như scrub hoặc resilver, vì dedup log không có khái niệm vị trí ổn định, khi có yêu cầu scan, hệ thống tăng tốc log flushing để phản ánh toàn bộ vào dedup ZAP rồi scan theo cách cũ

Quản lý unique entry và tính năng vận hành

  • zpool ddtprune xóa một phần unique entry khỏi dedup table của pool
    • Có thể chỉ định theo tiêu chí age hoặc percentage
    • Tiêu chí age đặc biệt phù hợp với workload mà dữ liệu được dùng gần đây có khả năng lại bị trùng lặp cao
  • Nếu một block có dedup entry đã bị loại bỏ bằng pruning được sao chép về sau, nó sẽ không được khử trùng lặp với block cũ mà được cấp phát thành block mới
    • Tuy nhiên, nếu một unique block cũ đột nhiên được sao chép nhiều lần, có thể sinh ra nhiều tham chiếu tới một block mới
  • Pool property dedup_table_quota giới hạn kích thước tối đa của dedup table
    • Nếu việc tạo entry mới vượt quá giới hạn, hệ thống không tạo entry mà xử lý như một lần ghi non-dedup thông thường
    • Có thể dùng kèm để tránh tràn sang main device khi dedicated dedup device bị đầy
  • zpool prefetch -t ddt nạp trước dedup table vào ARC
    • Có thể giúp cải thiện hiệu năng ngay sau khi import pool
    • Tính năng này vẫn hữu ích với Fast Dedup vì việc lookup entry không có trong log và flush vẫn cần truy cập ZAP
  • Các kstats và tuneable mới cũng được bổ sung
    • Linux: /proc/spl/kstat/zfs/<pool>/ddt_stats_<checksum>
    • FreeBSD: kstat.zfs.<pool>.misc.ddt_stats_<checksum>
    • Linux tuneable: /sys/modules/zfs/parameters/zfs_dedup_log_*
    • FreeBSD tuneable: vfs.zfs.dedup.log_*
  • Các công cụ hiện có có nhận biết dedup như zpool status -D, zdb -D, zdb -S cũng được cập nhật để hiểu cấu trúc mới

Tương thích với dedup table cũ

  • Phần lớn Fast Dedup cần thay đổi on-disk format, nên không áp dụng nguyên trạng cho dedup table cũ
  • Một số tính năng không cần thay đổi định dạng on-disk vẫn có thể hoạt động với table cũ
    • dedup_table_quota
    • zpool prefetch -t ddt
    • lookup và hit count ddt_stats_*
    • ZAP shrink
  • Việc làm cho dedup log hoạt động cả với table truyền thống vẫn còn là một nhiệm vụ tương đối straightforward
    • Tuy nhiên, sẽ không có được lợi ích từ live/log entry nhỏ hơn
  • Với table cũ, zpool ddtprune dễ bổ sung nhất ở chế độ “percentage of uniques”
    • Chế độ age cần dữ liệu của entry format mới, nên không thể thực hiện với format cũ
  • Hiện chưa có tính năng chuyển đổi table cũ sang format mới
    • Trong trường hợp đơn giản, khi copies= chưa từng thay đổi, có thể tạo ZAP mới rồi chuyển đổi và sao chép entry cũ
    • Chuyển đổi online phức tạp vì cần lookup hoặc ghi đồng thời cả ZAP old/new
    • Chuyển đổi offline dễ hơn nhưng phải đưa pool xuống offline
    • Nếu việc thay đổi copies= đã tạo nhiều variant có refcount, có thể không thể chuyển đổi hoàn toàn
  • Cách gửi một deduplicated dataset sang pool khác có hỗ trợ dedup mới vẫn hoạt động

“Đã tốt hơn, nhưng vì sao không nên bật?”

  • Fast Dedup giảm overhead so với trước, nên có thể hữu ích trong nhiều tình huống cận biên hơn
  • Nhưng dedup vẫn là bài toán cân bằng giữa thông lượng IO, mức dùng bộ nhớ và kích thước dedup table
  • Với workload mục đích chung, các block có thể trùng lặp có thể cực kỳ hiếm
  • Kết quả simulated DDT bằng zdb -S trên pool laptop ví dụ cho thấy lợi ích dedup gần như không có
    • Phần lớn 11,7 triệu entry là unique entry có refcount 1
    • Số entry thực sự có thể dedup chỉ ở mức sai số làm tròn trên tổng thể
    • Hiển thị là dedup = 1.00
  • Trong trường hợp như vậy, bật dedup gần như không đem lại gì mà chỉ tăng áp lực IO và bộ nhớ

Khi BRT/block cloning tốt hơn

  • Từ OpenZFS 2.2 có BRT, tức block cloning hoặc reflinks
  • Dedup table là cấu trúc để biết “dữ liệu này đã có trên đĩa chưa” mà không cần ngữ cảnh
  • Trong các hệ thống hiện đại, đôi khi thao tác sao chép có thể được truyền xuống storage stack như chính một thao tác sao chép
    • copy_file_range() của filesystem trên Linux và FreeBSD
    • copyfile() của macOS
    • FSCTL_SRV_COPYCHUNK của Windows
    • NFS, CIFS, OS block device driver, SCSI EXTENDED COPY, NVMe Copy, v.v. cũng có chức năng tương tự
  • Nếu chương trình client và các tầng trung gian truyền tín hiệu copy offload, OpenZFS có thể chỉ tăng refcount trong BRT
  • BRT không phát sinh chi phí nếu block không được clone, và khi được clone thì entry chỉ 16 byte
  • Trong pool ví dụ, BRT cho kết quả used 292M; saved 309M; ratio 2.05x
  • Mức tiết kiệm raw hơi thấp hơn và tương đương với mô phỏng dedup, nhưng không có chi phí lớn để theo dõi toàn bộ các block không được clone

Tiêu chí thực tế để quyết định

  • Fast Dedup cải thiện cả ba trục của dedup truyền thống: IO throughput, memory usage và dedup table size
  • Chi phí thảm họa khi thất bại cũng giảm, và người vận hành có thêm công cụ để giới hạn/dọn dẹp table
  • Dù vậy, để có lợi thì điều kiện phải rõ ràng
    • Quy mô dữ liệu phải rất lớn
    • Cùng dữ liệu phải được sao chép nhiều
    • Không thể dùng các lựa chọn zero-copy khác của OpenZFS như block cloning hoặc snapshot clone
  • Nếu workload có thể gửi tín hiệu rõ ràng rằng client “hãy sao chép”, block cloning có thể đem lại lợi ích lớn với chi phí thấp hơn

1 bình luận

 
GN⁺ 2024-10-31
Ý kiến trên Hacker News
  • Sẽ rất tốt nếu có khử trùng lặp ngoại tuyến, hoặc khử trùng lặp trì hoãn không cần hạ toàn bộ pool xuống nhưng cũng không chạy ngay lập tức
    Khi bật khử trùng lặp, mỗi lần ghi và giải phóng đều cần tra cứu và ghi vào bảng khử trùng lặp, điều này trong hầu hết trường hợp có vẻ là cách tiếp cận sai. Khi ghi dữ liệu, người ta muốn hoàn tất nhanh nhất có thể dù có tốn thêm dung lượng đĩa, và đó là lý do không lưu các tệp đang làm việc bên trong một archive 7zip. Sẽ tốt hơn nếu sau này, khi hệ thống rảnh, ZFS tìm dữ liệu trùng lặp và thu hồi dung lượng bằng thứ gì đó như BRT; việc này dường như cũng có thể được làm như một phần của thao tác scrub thông thường

    • Khử trùng lặp trì hoãn/ngoại tuyến cần ghi lại con trỏ khối, nhưng ZFS không phải là một hệ thống CAS thực sự nên có lẽ cũng khó có được BP rewrite đúng nghĩa trong tương lai
      Vì vị trí vật lý được băm vào cây băm Merkle, để di chuyển vị trí vật lý thì phải ghi lại tất cả các nút nội bộ trên đường tới nút cần thay đổi, nên chi phí quá lớn. Thiết kế tốt hơn lẽ ra là tách mọi nút có con trỏ khối thành một phần chỉ chứa con trỏ khối logic và được băm vào cây, và một phần chỉ chứa vị trí vật lý tương ứng với con trỏ logic đó như một bộ nhớ đệm nhưng không được băm vào cây Merkle. Khi đó BP rewrite chỉ cần ghi lại các khối không thuộc cây Merkle. Với cấu trúc hiện tại, khó có được chức năng mong muốn trong ZFS, nhưng có thể có một cách vòng: khi đọc mà phát hiện hash không khớp, dùng hash của con trỏ để tìm khối trong bảng khử trùng lặp rồi cấp phát lại khối đã được khử trùng lặp. Cái giá chỉ cỡ một lần đọc vô ích, nên không quá tệ; nhưng khi không thể BP rewrite thì thường sẽ xuất hiện những miếng vá kiểu này
    • Cách này giống phương pháp khử trùng lặp của Windows. Tôi đã dùng khá nhiều, và nếu phần cứng đủ mạnh thì nhìn chung khá hài lòng
      Nó ngốn nhiều RAM và I/O, nhưng có thể lập lịch và giới hạn “groveler”. Tuy nhiên tôi từng gặp hỏng dữ liệu bị nuốt mất do một lỗi thời Windows 2012 R2
    • Việc này cũng có thể làm bằng công cụ phát hiện tệp trùng lặp ngoại tuyến
      Ví dụ có jdupes hoặc duperemove. Tôi đã gửi PR cho phía ZFS và phía duperemove để hỗ trợ các system call cần thiết. Phía ZFS mất nhiều thời gian review, và tôi nhận ra mình đã quên hoàn tất hẳn việc đó nên phải quay lại xử lý
    • Khả năng thay đổi các snapshot hiện có trong ZFS là cực kỳ hạn chế, ngay cả theo cách dữ liệu được bảo toàn hoàn toàn. Vì vậy có chức năng như vậy thì tốt, nhưng nếu đã chờ Block Pointer Rewrite thì hẳn nó đã chết từ lâu rồi
    • Điểm hay của khử trùng lặp inline là nếu hash của khối đã tồn tại thì không cần thực sự ghi khối đó
      Trong nhiều tình huống, nó có thể giảm mạnh I/O ghi. Trong các mảng lưu trữ có khử trùng lặp, còn có phần mở rộng mà khi sao chép tệp giữa hai VM, dữ liệu thực không được sao chép mà chỉ tăng bộ đếm tham chiếu của khối gốc. Trên hệ điều hành, nó trông như tốc độ ghi phi lý ở mức TB/s, khá thú vị
  • Lập luận rằng “vấn đề căn bản của khử trùng lặp truyền thống là overhead lớn đến mức khó thu hồi lại nếu không phải những workload hiếm và đặc thù” nghe khá lạ
    Tôi đã làm việc với các mảng Pure và Dell/EMC, và với workload VMWare thì thường tiết kiệm ít nhất 3:1 nhờ khử trùng lặp/nén. Cách chỉ lưu một bản sao của image VM nền hoạt động rất tốt. Trên máy chủ syslog, khử trùng lặp/nén cũng phát huy hiệu quả và tôi từng thấy mức tiết kiệm 6:1. Hiệu quả khử trùng lặp phụ thuộc rất nhiều vào kích thước khối được băm, càng nhỏ càng tốt. Khi khối nhỏ hơn, xác suất có khối khớp tăng nhanh; theo kinh nghiệm, kích thước khối tôi thích là 4KB

    • Image VM là thông tin có độ trùng lặp rất cao, giống như ổ C của các image Windows Server hầu như giống nhau, còn bài gốc lấy nội dung trên laptop của tác giả làm ví dụ
      Ngoài ra có vẻ đang trộn lẫn hai chức năng khác nhau là nén và khử trùng lặp. Trong ZFS có thể bật nén cho pool và điều đó hầu như luôn đáng làm, nhưng có thể để tắt khử trùng lặp
    • Image VM nền là workload hiếm và đặc thù, là một trong số ít trường hợp khử trùng lặp có ý nghĩa
      Tuy nhiên nếu host VM trên một hệ thống tệp ZFS, nhiều khả năng bạn đang dùng các chiến lược tốt hơn như clone ở cấp khối hoặc hệ thống tệp. Không làm vậy tức là bỏ qua một trong những điểm khác biệt cốt lõi của ZFS trong môi trường đó. Với máy chủ tệp đa dụng hoặc desktop/laptop cá nhân, thường có rất ít khối trùng lặp nên overhead là không đáng. Backup có thể phù hợp hoặc không, tùy cách triển khai và việc dữ liệu có được mã hóa trước lớp hệ thống tệp hay không. Nén là câu chuyện hoàn toàn khác, và best practice hiện nay của ZFS là bật mặc định cho gần như mọi workload. Ngày nay chi phí CPU nhỏ đến mức hầu như không đáng nhắc tới, và ngoài tiết kiệm dung lượng lưu trữ, nó còn có thể giảm I/O đáng kể. Với kho log thông thường, theo kinh nghiệm có thể đạt mức tiết kiệm tốt hơn nhiều so với 6:1
    • Tôi chưa tự thử, nhưng con số thường được trích dẫn rộng rãi về khử trùng lặp ZFS cũ là cần 5GB RAM cho mỗi 1TB đĩa
      Nếu hiện nay 1TB đĩa khoảng 15 đô la và 5GB RAM máy chủ khoảng 25 đô la, thì chỉ để hòa vốn cũng cần tỷ lệ khử trùng lặp 3:1. Nếu dữ liệu phù hợp, có thể trụ được với 1GB mỗi TB, nhưng nếu xui thì 5GB cũng có thể không đủ. Vì vậy bài viết nói khử trùng lặp của ZFS có một sweet spot nhỏ, nơi dữ liệu phải vừa khớp, và đó là lý do đa số không bận tâm. Các hệ thống tệp khác thường chuộng khử trùng lặp ngoại tuyến vì tính kinh tế tốt hơn
    • VM là nơi lợi ích của khử trùng lặp đã được biết đến, nên có thể thấy hiệu quả ở đó. Nhưng ZFS không chỉ là SAN doanh nghiệp mà là hệ thống tệp đa dụng, nên không phải nhiều người dùng ZFS đều chạy VM
      Việc nói khử trùng lặp/nén hiệu quả với syslog, xét chi tiết thì khử trùng lặp và nén không phải là cùng một thứ. Trong thế giới lưu trữ doanh nghiệp, hai thứ này thường được gộp lại, nhưng log có lẽ hưởng lợi từ nén chứ không phải khử trùng lặp, và ZFS vốn đã có nén từ đầu
    • Việc không tạo nhiều bản sao sâu của image VM nền hiển nhiên là hợp lý, nhưng trong ZFS thì khử trùng lặp không phải là cách phù hợp
      Thay vào đó, nếu clone image nền thì trước khi có thay đổi, nó hầu như không chiếm dung lượng. Điều này nhờ đặc tính copy-on-write của ZFS. Khử trùng lặp ZFS là chức năng cố tìm bản sao hiện có của dữ liệu được ghi vào volume. Với một số mục đích như kho image container, nó có thể khá hợp lý, nhưng nếu ngay từ đầu đã biết một dataset là clone của dataset khác thì cách đó rất kém hiệu quả
  • Trước đây ZFS deduplication từng được dùng rộng rãi và mang lại lợi ích lớn. Trường hợp sử dụng cụ thể là lưu trữ cho cụm VMWare, với hàng trăm VM Linux và Windows có nội dung phần lớn giống nhau. Đó là câu chuyện thời trước Docker

    • Ở đây thấy có nhiều ví dụ dùng deduplication cho VM, nhưng tôi nghĩ việc này nếu triển khai ở hypervisor thì có lẽ hiệu quả hơn nhiều so với ở filesystem
    • Đồng cảm. Gần đây tôi nhận một laptop làm việc mới có zfs “experimental” của Ubuntu, và việc dùng deduplication cho nix store thực sự giúp ích rất nhiều
  • Rất mong chờ deduplication nhanh. Suốt vài năm tôi đã muốn dùng ZFS deduplication cho dữ liệu ArchiveBox, và nhờ deduplication nhanh, có vẻ cuối cùng sẽ có thể lưu trữ hàng triệu URL trong một bộ sưu tập rồi để filesystem lo phần nén toàn cục
    Trong dữ liệu lưu trữ, những thứ như jquery.min.js, bootstrap.min.css, ảnh logo xuất hiện lặp lại trong hàng nghìn snapshot. Các công cụ khác nén trong phạm vi một lần crawl để tạo file wacz hoặc warc.gz, nhưng dường như chưa công cụ nào thử nén xuyên suốt toàn bộ cơ sở dữ liệu của mọi snapshot đã chụp từ trước tới nay. Tôi cũng tò mò liệu đã có ai thử cách tiếp cận deduplication xác suất dùng thứ như Bloom filter để khỏi phải lưu nguyên cả bảng băm deduplication toàn cục hay chưa. Gom khoảng 100 hash khối thành một bucket, rồi lưu biểu diễn siêu nén trong Bloom filter. Khi ghi, tra hash của khối sắp ghi trong Bloom filter; nếu phát hiện khả năng trúng deduplication, thì quét trực tiếp 100 khối trong bucket đó để tìm hash giống hệt. Về lý thuyết có thể có các tầng Bloom filter với độ phân giải khác nhau, và khi áp lực bộ nhớ cao thì đẩy động filter độ phân giải cao xuống đĩa. Nếu đặt độ chính xác Bloom filter làm tham số có thể điều chỉnh, người dùng có thể chọn ưu tiên giữa thời gian CPU/overhead và tỷ lệ byte tiết kiệm được

    • Ngay cả với thay đổi này, ZFS deduplication vẫn dựa trên căn chỉnh khối, nên nếu các web asset lặp lại không luôn nằm ở cùng offset trong kho lưu trữ WARC thì sẽ khó khớp
      dm-vdo cũng hoạt động tương tự. Thay vào đó có thể tốt hơn nếu dùng solid compression nhìn trên phạm vi dài, hoặc bung file WARC thành cấu trúc gần giống thư mục, hoặc nếu có hệ thống FUSE dựa trên content-defined chunking thì dùng hướng đó. Có thể Seafile là như vậy
    • Tôi hiểu trường hợp sử dụng, nhưng trong đa số tình huống, đặc biệt là trường hợp này, có lẽ triển khai phía client sẽ tốt hơn nhiều
      Nhìn vào chuẩn WARC thì đã có cơ chế deduplication dựa trên hash, sau lần lưu đầu tiên sẽ dùng con trỏ. Vì vậy đây đúng là ví dụ mà deduplication ở tầng filesystem không mấy phù hợp
    • Trường hợp sử dụng hơi khác, nhưng nếu chưa biết zbackup thì có thể bạn sẽ thích
  • Tôi thắc mắc vì sao lại khó đến vậy để khiến thứ này hoạt động đúng trong khi giảm lượng RAM dùng. Các appliance lưu trữ thương mại đã làm được từ ít nhất khoảng 10 năm trước, ngay cả trên hệ thống có RAM “ít” so với dung lượng đĩa gắn kèm
    Tôi nghĩ chỉ cần lưu fingerprint vào database rồi ban đêm quét qua và sửa block pointer là được không phải sao

    • “Sửa block pointer” chính là lý do. Vì nhiều lý do, ZFS không có khả năng ghi lại block pointer
      Đây là tính năng đã được yêu cầu từ lâu, và nếu có thì cũng có thể chống phân mảnh. Tôi từng nghĩ có thể giải quyết bằng cách dùng gián tiếp hóa block pointer như bộ nhớ ảo, đổi lại một chút chi phí tốc độ, nhưng tôi không phải lập trình viên ZFS nên chắc chắn đang bỏ sót điều gì đó. http://eworldproblems.mbaynton.com/posts/2014/zfs-block-poin... / https://github.com/openzfs/zfs/issues/3582
    • Sửa block pointer chính là điều duy nhất ZFS cố tránh làm
    • Cũng có thể dùng DragonFlyBSD và Hammer2. Hammer2 hỗ trợ cả deduplication online lẫn offline và ở nhiều mặt rất giống ZFS
      Nhược điểm lớn là không có giao thức truyền file dùng RDMA. Tôi nghe nói cũng có nhánh thử nghiệm để chạy Hammer2 trên FreeBSD. Nhưng FreeBSD cũng không có hỗ trợ RDMA. Trong FreeBSD 15, Chelsio đã tài trợ hỗ trợ NVMe-oF target và initiator, nhưng có vẻ chỉ là TCP
  • Dùng cp --reflink=auto là được
    Có thể có deduplication ở cấp file. Lệnh này thực hiện bản sao nhẹ; giống như clone ZFS ở cấp file, các block dữ liệu chỉ được sao chép khi bị sửa đổi. Đây là bản sao chứ không phải hard link. Cách này cũng sẽ hoạt động tương tự trên các filesystem giao dịch copy-on-write khác có hỗ trợ reflink

  • Tôi rất muốn dùng ZFS, nhưng dĩ nhiên mọi dữ liệu đều phải được mã hóa. Thế nhưng cách dùng trở nên phức tạp hơn nhiều so với dự đoán, và khi mọi thứ rối lên thì điều đáng ngạc nhiên là nhiều người đơn giản không mã hóa dữ liệu
    Ngay cả Proxmox có chữ “Enterprise” trên website nên tôi tưởng bản cài mặc định sẽ hỗ trợ mã hóa, nhưng nếu muốn dùng cùng mã hóa thì lại mất các tính năng quan trọng. Cũng nhất định nên xem issue tracker. Có vài điều đáng ngạc nhiên mà tôi không ngờ lại có trong một filesystem vận hành thực tế

    • Cách tốt nhất để mã hóa ZFS là đặt ZFS không mã hóa lên trên một volume đã mã hóa, chẳng hạn volume LUKS. “Mã hóa” của ZFS để lại quá nhiều thứ ở dạng plaintext nên khiến tôi bất an
  • Tôi ước có một API hoàn toàn khác cho filesystem. Bề mặt API filesystem của mọi hệ điều hành đều là một mớ hỗn độn bị mắc kẹt vì tương thích ngược

    • Về nội bộ, ZFS về bản chất là object store. Đã từng có công việc nhằm phơi bày nó dưới dạng API object store, nhưng đáng tiếc là có vẻ không đi đến đâu
      Tôi đã cố tìm bài trình bày nhưng không thành. Tôi tưởng đã thấy ở Developer Summit, nhưng có lẽ không phải
    • Vì sao lại là mớ hỗn độn và có thể thay bằng gì? API kiểu AWS S3 có phải là một cải tiến không?
  • Quên deduplication đi, dùng nén ZFS thì hiệu quả chi phí tốt hơn nhiều

    • Ngoại lệ là nếu dataset đã là các file media được nén mạnh
      Thường thì ngay cả trong các tác vụ rsync, tôi cũng tắt nén với những file video lớn. Vì nén ít hiệu quả, hoặc thậm chí không có tác dụng, đối với lưu trữ hay truyền tải, nhưng lại tốn RAM và CPU. Deduplication phù hợp với image OS của Virtual Machine, vì phần lớn chi phí lưu trữ nằm ở image nền bị lặp lại
  • Về lý thuyết, khử trùng lặp dùng chung trông có vẻ hay, nhưng trên thực tế thường không suôn sẻ. IPFS, giống như rsync, sử dụng các mảnh có kích thước thay đổi và rolling hash để khử trùng lặp dữ liệu, nhưng thực tế lại không tạo ra khác biệt mà chỉ làm tăng thêm độ phức tạp không cần thiết