Redis Persistence
Redis Persistent là tính năng của Redis cho phép lưu trữ dữ liệu trên đĩa cứng (disk storage) để đảm bảo sự an toàn dữ liệu khi có sự cố xảy ra và khả năng khôi phục sau khi khởi động lại hệ thống.
Trong bài viết này chúng ta sẽ cùng tìm hiểu những cơ chế Persistence mà Redis cung cấp:
RDB (Redis Database): lưu trữ bản chụp dữ liệu tĩnh (snapshot) của Redis tạo một thời điểm nhất định
AOF (Append Only File): ghi lại mọi thao tác write (thao tác ghi) mà server nhận được. Khi Redis khởi động lại, các thao tác này sẽ được thực hiện lại, tái tạo lại dataset ban đầu.
No Persistent: Có thể sử dụng trong 1 số trường hợp caching.
RDB + AOF: Bạn cũng có thể kết hợp cả RDB và AOF trong cùng một thể hiện.
I. RDB (Redis Database)
Là một phương pháp lưu trữ bản chụp dữ liệu tĩnh (snapshot) của Redis tạo một thời điểm nhất định. Quá trình này tạo ra một file duy nhất chứa toàn bộ dữ liệu ở dạng nén, giúp dễ dàng khôi phục lại trạng thái của dữ liệu.
Cách RDB hoạt động:
Khi cần tạo snapshot, Redis sử dụng lệnh fork để tạo ra một tiến trình con. Trong khi đó tiến trình cha (tiến trình gốc) tiếp tục xử lý yêu cầu từ clients. Tiến trình cha và tiến trình con ban đầu sẽ chia sẻ cùng một không gian bộ nhớ.
Tiếp tục, tiến trình con sẽ bắt đầu ghi dữ liệu của dataset hiện tại vào một file RDB tạm thời. Quá trình này không ảnh hưởng đến hiệu suất của tiến trình cha nhờ vào kỹ thuật copy-on-write, nơi mà các thay đổi dữ liệu mới sẽ không làm ảnh hưởng đến dữ liệu đang được ghi.
Sau khi việc ghi hoàn tất việc ghi dữ liệu, file RDB mới sẽ thay thế file RDB cũ.
Copy-On-Write
Và để có thể tối ưu về mặt hiệu suất kỹ thuật copy-on-write được Redis áp dụng một cách linh hoạt như sau:
Khi Redis cần tạo một bản chụp dữ liệu, nó sử dụng lệnh fork để tạo ra một tiến trình con từ tiến trình cha. Tiến trình cha và tiến trình con ban đầu sẽ chia sẻ cùng một không gian bộ nhớ.
Sau khi fork, cả hai tiến trình đều có quyền truy cập vào các trang bộ nhớ giống hệt nhau tại thời điểm fork. Trong trường hợp không có thay đổi, không có sự sao chép thực sự nào xảy ra, vì vậy không có bộ nhớ mới nào được phân bổ.
Nếu tiến trình cha thực hiện thay đổi trên một trang bộ nhớ mà cả hai tiến trình đều đang sử dụng, hệ điều hành sẽ sao chép trang đó trước khi thay đổi. Trang bộ nhớ mới được tạo ra cho tiến trình cha để thay đổi, trong khi tiến trình con vẫn giữ nguyên bản của trang bộ nhớ tại thời điểm fork.
Kết thúc tiến trình con: Khi tiến trình con hoàn tất công việc của mình (ghi dữ liệu vào file RDB) và kết thúc, hệ điều hành sẽ giải phóng bộ nhớ mà tiến trình đó đã sử dụng. Tuy nhiên, điều quan trọng cần lưu ý là:
Các trang bộ nhớ mà không có thay đổi nào (vẫn còn được chia sẻ giữa cha và con) sẽ không được giải phóng ngay lập tức bởi vì chúng vẫn đang được tiến trình cha sử dụng.
Chỉ các bản sao mới của trang bộ nhớ—những trang mà tiến trình cha đã thay đổi sau khi
fork()—có thể được giải phóng khi tiến trình con kết thúc, vì chúng không còn được tiến trình con sử dụng nữa
RDB advantages
Tối Ưu Hóa Việc Sao Lưu Dữ Liệu: RDB lưu trữ dữ liệu của Redis trong một file duy nhất, nhỏ gọn, chứa trạng thái dữ liệu tại một thời điểm cụ thể. Điều này làm cho RDB trở thành một lựa chọn lý tưởng cho việc sao lưu vì nhiều lý do:
Dễ Dàng Sao Lưu và Khôi Phục: Một file duy nhất giúp việc sao lưu và khôi phục dữ liệu trở nên đơn giản và nhanh chóng.
Tiện Lợi trong Việc Di Chuyển: File RDB có thể dễ dàng được chuyển đến các trung tâm dữ liệu xa hoặc lưu trữ trên các dịch vụ như Amazon S3, cũng có thể được mã hóa để bảo vệ dữ liệu.
Hiệu Quả Trong Việc Phục Hồi Sau Sự Cố: Khi có sự cố xảy ra, việc phục hồi hệ thống là ưu tiên hàng đầu. RDB cung cấp các ưu điểm vượt trội trong tình huống này:
Phục Hồi Nhanh Chóng: Do là một file duy nhất và thường nhỏ gọn, RDB cho phép khôi phục dữ liệu một cách nhanh chóng, giảm thiểu thời gian hệ thống không hoạt động.
Khởi Động Nhanh Chóng hơn so với AOF: RDB cho phép Redis khởi động lại nhanh hơn sau sự cố, đặc biệt khi so sánh với phương pháp AOF (Append Only File), vì việc đọc một file duy nhất thường nhanh hơn là xử lý nhiều ghi chép trong AOF
Tối Đa Hóa Hiệu Suất của Redis: Trong hoạt động hàng ngày của Redis, RDB đóng một vai trò quan trọng trong việc tối đa hóa hiệu suất:
Giảm Tải I/O Đĩa: Tiến trình chính của Redis không bao giờ thực hiện thao tác I/O trên đĩa. Việc này giảm tải cho tiến trình chính, cho phép nó xử lý các yêu cầu một cách nhanh chóng mà không bị chậm lại bởi quá trình ghi đĩa.
Tách Biệt Quá Trình Lưu Trữ: Việc sử dụng một tiến trình con để xử lý tất cả công việc liên quan đến bản chụp giúp tối ưu hoạt động của tiến trình chính.
RDB disadvantages
Nguy Cơ Mất Dữ Liệu
Snapshot tại Thời Điểm Cụ Thể: RDB lưu trữ dữ liệu dưới dạng bản chụp tại thời điểm nhất định. Nếu Redis ngừng hoạt động đột ngột (như trong trường hợp mất điện hoặc sự cố phần cứng), tất cả dữ liệu đã ghi từ lần bản chụp cuối cùng cho đến khi sự cố xảy ra sẽ bị mất. Điều này không lý tưởng cho các ứng dụng yêu cầu tính toàn vẹn dữ liệu cao hoặc khi dữ liệu được cập nhật liên tục và mọi mất mát, dù nhỏ, cũng có thể dẫn đến hậu quả nghiêm trọng.
Chi Phí của Việc Sử Dụng Lệnh
fork()Khi Redis thực hiện sao lưu RDB, tiến trình cha sẽ sử dụng lệnh
fork()để tạo ra một tiến trình con. Tiến trình cha tiếp tục xử lý các yêu cầu, và nếu có sự thay đổi dữ liệu trong thời gian này, những trang bộ nhớ có sự thay đổi này sẽ được sao chép do cơ chế Copy-on-Write (COW). Điều này có thể làm tăng đáng kể lượng bộ nhớ sử dụng, đặc biệt nếu có nhiều trang bộ nhớ được thay đổi trong quá trình sao lưu.=> Vấn Đề Phát Sinh về Tình trạng bộ nhớ: Khi
fork()được gọi, hệ điều hành cần đảm bảo có đủ bộ nhớ cho tiến trình con để sao chép các trang bộ nhớ nếu có thay đổi. Nếu hệ thống không có đủ bộ nhớ trống, quá trìnhfork()có thể thất bại, dẫn đến lỗi như "Cannot allocate memory".Vấn Đề Với Dataset Lớn: Khi dataset lớn, việc thực hiện fork có thể trở nên rất tốn kém về mặt thời gian và tài nguyên hệ thống. Khi không gian bộ nhớ được sao chép, nếu dataset rất lớn, quá trình này có thể dẫn đến độ trễ đáng kể. Trong vài trường hợp, điều này có thể gây ra độ trễ vài mili giây và thậm chí đến một giây, ảnh hưởng đến khả năng phục vụ của Redis đối với các yêu cầu từ client.
Hiệu Suất CPU: Việc fork cũng phụ thuộc vào hiệu suất của CPU. Trên các máy chủ có hiệu suất CPU thấp hoặc quá tải, quá trình này càng trở nên chậm chạp, có thể ảnh hưởng đến hiệu suất tổng thể của Redis và ảnh hưởng đến việc xử lý yêu cầu của người dùng.
II. AOF(Append Only File)
Là một cơ chế lưu trữ của Redis, ghi lại mọi thao tác write (thao tác ghi) mà server nhận được. Khi Redis khởi động lại, các thao tác này sẽ được thực hiện lại, tái tạo lại dataset ban đầu. Các lệnh được ghi lại theo định dạng của giao thức Redis.
Cách AOF hoạt động:
1. Save to AOF buffer
Khi Redis nhận được một lệnh ghi (ví dụ: SET, DEL), lệnh này sẽ được thực thi ngay lập tức để cập nhật dữ liệu trong bộ nhớ.
Đồng thời, lệnh ghi cũng sẽ được ghi vào bộ đệm AOF trong bộ nhớ. Bộ đệm này lưu trữ các lệnh ghi theo định dạng giao thức của Redis, tương tự như cách giao tiếp giữa Redis server và client.
2. Flushing of the buffer
Việc xả bộ đệm AOF sang tệp AOF trên đĩa được xác định bởi cài đặt appendfsync. Cài đặt này có thể có ba giá trị:
always: Xả bộ đệm sau mỗi lệnh ghi. Đây là cài đặt an toàn nhất nhưng ảnh hưởng đến hiệu suất. Trên thực tế, chính sách này rất chậm nhưng hỗ trợ group commit, vì vậy nếu có nhiều thao tác ghi song song, Redis sẽ cố gắng thực hiện một thao tác fsync duy nhất.
everysec: Xả bộ đệm mỗi giây. Đây là cài đặt cân bằng tốt giữa độ bền dữ liệu và hiệu suất (cài đặt mặc định). Nhưng bạn có thể mất 1 giây dữ liệu nếu xảy ra sự cố.
no: Hệ điều hành quyết định thời điểm xả bộ đệm. Đây là cài đặt có hiệu suất tốt nhất nhưng ít an toàn nhất.
3. Write to AOF file
Khi bộ đệm AOF được xả, hàm flushAppendOnlyFile
()sẽ ghi nội dung của bộ đệm vào tệp AOF trên đĩa. Tệp AOF được ghi theo kiểu chỉ ghi thêm, nghĩa là các lệnh ghi mới sẽ được thêm vào cuối tệp mà không ghi đè lên dữ liệu hiện có.
4. Data recovery
Khi khởi động lại Redis, server sẽ đọc tệp AOF và phát lại tất cả các lệnh ghi được ghi trong tệp. Quá trình này cho phép Redis khôi phục trạng thái dữ liệu trước khi khởi động lại.
AOF advantages
Tính Bền Vững Cao: AOF ghi lại mọi thao tác thay đổi dữ liệu vào cuối tệp, đảm bảo rằng mọi thay đổi đều được lưu trữ ngay lập tức. Điều này cung cấp tính bền vững cao vì tất cả các thao tác đều được ghi nhận một cách cẩn thận và tuần tự, giảm thiểu khả năng mất dữ liệu do sự cố như mất điện hoặc sự cố hệ thống.
Tính đáng tin cậy: Ngay cả khi nhật ký kết thúc bằng lệnh viết nửa chừng vì lý do nào đó (đĩa đầy hoặc lý do khác), công cụ redis-check-aof vẫn có thể khắc phục dễ dàng
Tự Động Viết Lại AOF khi file quá lớn: Redis có thể tự động viết lại AOF ở chế độ nền khi nó quá lớn. Việc ghi lại hoàn toàn an toàn vì trong khi Redis tiếp tục thêm vào tệp cũ, một tệp hoàn toàn mới sẽ được tạo với tập hợp thao tác tối thiểu cần thiết để tạo tập dữ liệu hiện tại và khi tệp thứ hai này sẵn sàng, Redis sẽ chuyển đổi việc ghi từ tệp cũ sang tệp mới một cách nguyên từ và sau đó bắt đầu thêm log vào tệp mới.
AOF disadvantages
Các tệp AOF thường lớn hơn các tệp RDB tương đương cho cùng một tập dữ liệu.
AOF có thể chậm hơn (tùy thuộc vào fsync): Ghi vào AOF có thể chậm hơn ghi vào RDB tùy thuộc vào cài đặt
fsync.fsync=everysec: Đồng bộ hóa dữ liệu với đĩa mỗi giây. Mặc dù hiệu suất vẫn rất cao, việc ghi vào AOF có thể chậm hơn một chút so với RDB vì cần thực hiện thêm thao tác đồng bộ.
fsync=always: Đồng bộ hóa dữ liệu với đĩa sau mỗi lệnh ghi. Đây là cài đặt an toàn nhất nhưng ảnh hưởng đến hiệu suất ghi nhiều nhất.
fsync=no: Hệ điều hành quyết định thời điểm đồng bộ hóa. Đây là cài đặt có hiệu suất tốt nhất nhưng cũng ít an toàn nhất về mặt dữ liệu.
AOF Rewrite
Trong Redis, khi bạn sử dụng AOF để lưu trữ dữ liệu, tất cả các thao tác thay đổi (như SET, DEL, v.v.) được ghi lại vào một tệp nhật ký. Qua thời gian, tệp này có thể trở nên rất lớn do nó chứa mọi thao tác thay đổi đã thực hiện, bao gồm cả những thay đổi đã trở nên vô nghĩa (ví dụ: một giá trị được thiết lập nhiều lần liên tiếp).
Để giải quyết vấn đề này, Redis cung cấp một quá trình gọi là "AOF Rewrite". Mục đích này là để tạo ra một tệp mới chứa tập hợp tối thiểu của các thao tác cần thiết để phục hồi tập dữ liệu hiện tại
Khi tệp AOF gốc đạt đến một kích thước nhất định hoặc theo lịch trình được cấu hình trước, Redis sẽ tự động khởi động quá trình viết lại AOF. Quá trình này diễn ra ngầm trong nền, không ảnh hưởng đến hoạt động bình thường của Redis, cho phép Redis tiếp tục xử lý yêu cầu từ các client mà không bị gián đoán.
Khởi Động Quá Trình Viết Lại AOF
Khởi Tạo: Quá trình bắt đầu với hàm
rewriteAppendOnlyFileBackground. Đây là lệnh được gọi tự động hoặc thủ công để khởi động việc viết lại file AOF. Mục đích là để tối ưu hóa và giảm kích thước của file AOF hiện tại.Fork: Tiếp theo, Redis thực hiện lệnh
fork(), tạo ra một tiến trình con. Tiến trình này sẽ có một bản sao của không gian bộ nhớ từ tiến trình cha tại thời điểmfork()được thực hiện. Cơ chế copy-on-write đảm bảo rằng tiến trình con có thể xem xét dữ liệu mà không bị ảnh hưởng bởi các thay đổi tiếp theo trong tiến trình cha.
Xử Lý Dữ Liệu trong Quá Trình Viết Lại
Hoạt Động của Tiến Trình Con:
Viết Lại: Tiến trình con sử dụng dữ liệu hiện tại trong bộ nhớ để ghi lại các thao tác cần thiết vào một file AOF tạm thời mới. Quá trình này được gọi là
rewriteAppendOnlyFile.Dữ Liệu Mới trong Quá Trình Viết Lại: Trong khi tiến trình con đang viết lại file, mọi thay đổi mới đến dữ liệu (do các lệnh từ người dùng) sẽ được ghi vào
aof_rewrite_buf.
Hoạt Động của Tiến Trình Cha:
Tiếp Tục Xử Lý Lệnh: Tiến trình cha tiếp tục xử lý các lệnh từ người dùng và ghi chúng vào
aof_bufnhư bình thườngĐồng Bộ Hóa Dữ Liệu: Lệnh
flushAppendOnlyFileđược sử dụng để xả dữ liệu từaof_bufsang file AOF gốc, đảm bảo rằng tất cả dữ liệu mới được ghi lại một cách an toàn.
Kết Thúc Quá Trình Viết Lại
Hoàn Thành và Đổi Tên File:
Khi tiến trình con hoàn thành việc viết file AOF tạm thời, Redis sẽ thực hiện một thao tác
renameđể đổi tên file AOF tạm thời thành tên file AOF chính thức (server.aof_filename).Đây là một thao tác nguyên tử, nghĩa là thay đổi được thực hiện ngay lập tức và toàn diện, đảm bảo không có sự gián đoạn hay mất mát dữ liệu nào xảy ra.
No Persistence
Có thể sử dụng trong 1 số trường hợp caching
RDB + AOF
Redis hỗ trợ tối ưu hóa hơn nữa để nén và phục hồi nhanh hơn. Như đã mô tả ở trên, việc viết lại các lệnh AOF có thể làm giảm đáng kể số lượng lệnh. Tuy nhiên, Redis cần thực thi khi khởi động để khôi phục trạng thái trước đó và nó vẫn gần như không nhỏ gọn như RDB vốn lưu trữ snapshot của dữ liệu tại một thời điểm.
Do đó, Redis hỗ trợ một lệnh cấu hình có tên aof-use-rdb-preamble aof-use-rdb-preamble
Khi tính năng aof-use-rdb-preamble được kích hoạt, phần đầu của file AOF sẽ được tạo ra dưới dạng một bản chụp RDB. Điều này bao gồm một snapshot nhanh của trạng thái dữ liệu tại thời điểm bắt đầu quá trình viết lại AOF.
Ghi Các Lệnh Sau Preamble: Sau khi phần preamble RDB, các lệnh thay đổi dữ liệu tiếp theo sẽ được ghi vào file AOF như bình thường. Quá trình này tiếp tục cho đến khi file AOF được viết lại tiếp theo.
Bằng cách kích hoạt aof-use-rdb-preamble, chúng ta thu được nhiều lợi ích đi kèm với RDB, đồng thời đảm bảo độ bền tốt hơn, bao gồm:
Khởi động lại nhanh hơn: Tùy thuộc vào thời điểm tệp AOF được ghi lại, hầu hết dữ liệu sẽ được lưu trữ trong phần mở đầu RDB. Khôi phục trạng thái khi khởi động từ phần mở đầu RDB hiệu quả hơn việc phải phát lại các lệnh riêng lẻ từ tệp AOF.
Nhỏ gọn hơn: Tệp RDB là một biểu diễn nhỏ gọn hơn so với các lệnh và đối số AOF có tiền tố dài.
Độ bền vững: Các lệnh do máy khách đưa ra vẫn có thể được thêm vào tệp AOF ngay sau khi được nhận, do đó đảm bảo các lệnh không nằm trong ảnh chụp nhanh có thể được phát lại khi khởi động.
Hạn chế chính của việc sử dụng phần mở đầu RDB là sự phức tạp tuyệt đối đi kèm với nó:
Người ta không còn có thể chỉ kiểm tra tệp AOF khi có sự cố xảy ra. Redis cung cấp các tập lệnh tiện ích để sửa các tệp AOF bị hỏng và các phiên bản mới hơn thậm chí còn khắc phục một số vấn đề nhất định khi khởi động.
Tuy nhiên, có một sự phức tạp nhất định đi kèm với việc viết lại các tệp AOF, không nên đánh giá thấp điều này. Một số trường hợp đặc biệt nhất định phải được xem xét và suy nghĩ cẩn thận, ví dụ: liệu có đủ dung lượng trên ổ đĩa lưu trữ tệp AOF hay không.







hay quá anh ơi