Redis khóa phân tán
Thực tếsv 88, khoảng một năm trước, về vấn đề an toàn của bộ phân phối Redis, các chuyên gia hệ thống phân tán Martin Kleppmann và tác giả của Redis antirez Trong khoảng thời gian đósv 88, đã xảy ra một cuộc tranh luận khá gay gắt. Do tôi luôn quan tâm đến vấn đề này từ trước, nên cách đây không lâu, tôi đã dành thời gian kỹ lưỡng để nghiên cứu các tài liệu liên quan đến cuộc tranh luận này. Nội dung chính của cuộc tranh luận như sau: Để đảm bảo tính an toàn hơn cho việc triển khai bộ nhớ đệm phân tán dựa trên Redis, tác giả của Redis đã đưa ra một phương án mới được thiết kế cẩn trọng hơn, có tên gọi là **Redlock**. Mục đích của Redlock là giải quyết các vấn đề tiềm ẩn trong việc sử dụng cơ chế khóa phân tán với Redis, chẳng hạn như sự đồng bộ dữ liệu giữa các nút hoặc xung đột khi có nhiều tiến trình cùng thực hiện yêu cầu đồng thời. Tuy nhiên, ý tưởng này cũng vấp phải nhiều ý kiến trái chiều từ cộng đồng phát triển phần mềm, vì nó đòi hỏi một số điều kiện phức tạp để triển khai đúng cách. Redlock Một ngày nọtỷ lệ kèo bóng đá trực tiếp, Martin Kleppmann đã viết một bài blog phân tích những vấn đề tồn tại trong tính an toàn của Redlock. Sau đótỷ lệ kèo bóng đá trực tiếp, tác giả của Redis ngay lập tức viết một bài blog Người ta đã cố gắng phản bác lại phân tích của Martin99win club, nhưng anh ấy khẳng định vẫn kiên trì với quan điểm ban đầu của mình. Điều này ngay lập tức trở thành tâm điểm tranh luận gay gắt trên Twitter và Nhiều chuyên gia hàng đầu trong lĩnh vực hệ thống phân tán đã tham gia vào cuộc thảo luận sôi nổi này, đưa ra những góc nhìn đa dạng và sâu sắc từ kinh nghiệm cá nhân của họ.
Đối với những ai quan tâm đến hệ thống phân tán99win club, sự kiện này chắc chắn đáng để theo dõi. Dù bạn là người mới bắt đầu làm quen với hệ thống phân tán hay một chuyên gia dày dặn kinh nghiệm trong lĩnh vực này, việc đọc qua các phân tích và nhận xét có thể mang lại cho bạn nhiều điều thú vị. Hãy nhớ rằng, Antirez - người đã tự tay xây dựng Redis Cluster, một hệ thống phức tạp như vậy, xứng đáng được coi là một chuyên gia trong lĩnh vực hệ thống phân tán. Tuy nhiên, khi các chuyên gia khác cùng tham gia vào việc phân tích vấn đề liên quan đến khóa phân tán, họ thường đưa ra những kết luận hoàn toàn khác biệt. Điều đó cho thấy mức độ phức tạp của các vấn đề liên quan đến hệ thống phân tán. Thực tế, trong quá trình thiết kế hệ thống phân tán, rất thường xuyên xảy ra tình huống mà ý tưởng ban đầu dường như hoàn hảo nhưng khi suy xét kỹ lưỡng, nó lại không còn hoàn hảo như ban đầu nữa.
Bây giờ99win club, chúng ta sẽ lần lượt xem lại và phân tích các quan điểm của các bên trong suốt quá trình tranh luận này. Trong quá trình đó, việc đi sâu ảnh hưởng của các chi tiết kỹ thuật đối với tính bảo mật của khóa phân tán chắc chắn sẽ rất thú vị. Đây cũng là một câu chuyện khá dài. Tất nhiên, không thể tránh khỏi việc xen kẽ vào đó một chút tích tắc về những câu chuyện hậu trường.
Giống như những gì đã đề cập ở phần đầu bài viết99win club, cách sử dụng Redis để triển khai một khóa phân tán (Distributed Lock) đã được nhiều người áp dụng. Mục đích của việc xây dựng loại khóa này là để quản lý và đảm bảo rằng các tài nguyên chung chỉ được truy cập một cách độc lập giữa các máy chủ hoặc tiến trình khác nhau. Điều này đặc biệt quan trọng trong các hệ thống lớn nơi mà nhiều dịch vụ cần đồng thời tương tác với cùng một nguồn dữ liệu.
Tuy nhiêntỷ lệ kèo bóng đá trực tiếp, mặc dù các phương án thực hiện này có xu hướng chung giống nhau, nhưng trong từng chi tiết lại hoàn toàn khác biệt. Điều này dẫn đến sự khác biệt về mức độ bảo mật và khả năng sử dụng mà chúng mang lại. Chính vì vậy, tác giả của Redis, antirez, đã đưa ra một giải pháp cải tiến hơn được gọi là Redlock, đây cũng có thể coi là hướng dẫn chuẩn từ phía Redis để triển khai khóa phân tán. Mô tả thuật toán của Redlock hiện đang được công bố trên trang web chính thức của Redis:
Trước khi Redlock xuất hiệnsv 88, hầu hết mọi người đều thực hiện cơ chế khóa phân tán dựa trên một nút Redis duy nhất. Trong khi đó, Redlock là một phương pháp được xây dựng dựa trên nhiều nút Redis (chỉ sử dụng các nút Master). Để có thể hiểu rõ về Redlock, trước tiên chúng ta cần làm rõ thuật toán đơn giản mà dựa trên một nút Redis duy nhất, vì đây chính là nền tảng của Redlock. Đơn giản hóa vấn đề từ việc sử dụng một nút Redis sẽ giúp chúng ta dễ dàng hình dung cách hoạt động của hệ thống. Khi chỉ có một nút Redis, việc quản lý khóa trở nên khá trực quan và không phức tạp như trong môi trường phân tán. Tuy nhiên, khi mở rộng lên nhiều nút, các vấn đề như sự đồng bộ giữa các nút hay xử lý lỗi sẽ trở thành thách thức lớn hơn. Chính vì vậy, việc nắm vững cơ chế cơ bản trên một nút sẽ tạo tiền đề quan trọng để tiếp cận giải pháp Redlock một cách hiệu quả.
Trước tiên, để Nhận được khóa sv 88, khách hàng Redis gửi lệnh sau đến nút Redis:
SET resource_name my_random_value NX PX 30000
Nếu lệnh trên được thực hiện thành công99win club, thì khách hàng đã nhận được khóa, tiếp theo có thể Truy cập tài nguyên chia sẻ ; còn nếu lệnh trên thất bại99win club, thì điều này có nghĩa là việc nhận khóa đã thất bại.
Lưu ý, trong lệnh
SET
ở trên:
my_random_value
Đây là một chuỗi ký tự ngẫu nhiên được tạo ra bởi clienttỷ lệ kèo bóng đá trực tiếp, và nó cần đảm bảo rằng trong khoảng thời gian tương đối dài, chuỗi này sẽ luôn duy nhất trên tất cả các yêu cầu khóa của mọi client. Điều này giúp tránh xung đột khi nhiều client cùng cố gắng truy xuất hoặc sử dụng tài nguyên đồng thời. Chuỗi ký tự này đóng vai trò như một nhận dạng duy nhất để quản lý quyền kiểm soát và đảm bảo tính toàn vẹn cho quá trình xử lý.
NX
Chỉ khi key tương ứng không tồn tại thì mới có thể
resource_name
Cuối cùngsv 88, sau khi khách hàng hoàn tất thao tác với tài nguyên chia sẻ, thực hiện đoạn mã Lua Redis sau đây để
SET
Thành công. Điều này đảm bảo rằng chỉ có khách hàng thực hiện yêu cầu đầu tiên mới có thể nhận được khóatỷ lệ kèo bóng đá trực tiếp, trong khi tất cả các khách hàng khác sẽ không thể lấy được khóa cho đến khi nó được giải phóng. Ngoài ra, hệ thống cũng có cơ chế giám sát thời gian để tránh tình trạng khóa bị giữ vĩnh viễn nếu ứng dụng gặp lỗi hoặc không thể thực hiện thao tác giải khóa đúng hạn.
PX 30000
Khóa này có thời gian hết hạn tự động là 30 giây. Tất nhiên99win club, con số 30 giây chỉ là một ví dụ, khách hàng hoàn toàn có thể chọn thời gian hết hạn phù hợp với nhu cầu của mình. Việc điều chỉnh thời gian này giúp tăng tính linh hoạt và đảm bảo rằng khóa sẽ chỉ duy trì hiệu lực trong khoảng thời gian cần thiết, tránh những rủi ro không mong muốn.Giải phóng khóa Khi thực thi đoạn mã Lua nàytỷ lệ kèo bóng đá trực tiếp, cần truyền giá trị trước đó :
if redis.call("get"tỷ lệ kèo bóng đá trực tiếp,KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
Làm giá trị truyền vàosv 88, và truyền giá trị
my_random_value
Làm giá trị truyền vào.
ARGV[1]
Vấn đề thứ haisv 88, bước đầu tiên
resource_name
Làm giá trị truyền vào.
KEYS[1]
Nhiều bài viết trên mạng đã thực hiện bước này bằng hai lệnh Redis:
Đến đâysv 88, thuật toán về khóa phân tán dựa trên nút Redis đơn đã được trình bày xong. Trong quá trình này, có một số vấn đề quan trọng cần được phân tích sâu thêm. Đầu tiên là vấn đề về tính nhất quán của dữ liệu khi có nhiều yêu cầu truy cập cùng lúc. Khi các máy chủ cạnh tranh để có được quyền sở hữu khóa, chúng ta phải đảm bảo rằng chỉ có một máy chủ duy nhất có thể nhận được khóa và giữ nó trong suốt thời gian sử dụng. Điều này đòi hỏi cơ chế xử lý xung đột phải thật chặt chẽ. Thứ hai là vấn đề thời gian sống (lifetime) của khóa. Nếu thời gian khóa tồn tại quá ngắn, hệ thống có thể gặp rủi ro khi xảy ra lỗi mạng hoặc sự cố phần cứng khiến các yêu cầu không được thực hiện đầy đủ. Ngược lại, nếu thời gian sống quá dài, sẽ gây lãng phí tài nguyên và có thể dẫn đến các tình huống khóa bị chiếm giữ lâu hơn mức cần thiết. Cuối cùng, vấn đề xử lý trường hợp khóa bị bỏ sót hoặc không được giải phóng đúng cách cũng rất quan trọng. Khi một máy chủ giữ khóa gặp sự cố và không thể tự động giải phóng nó, cần có cơ chế dự phòng để đảm bảo rằng khóa vẫn có thể được mở và tiếp tục sử dụng cho các yêu cầu khác. Việc hiểu rõ những vấn đề này và đưa ra giải pháp phù hợp là bước quan trọng để đảm bảo tính ổn định và hiệu quả của hệ thống phân tán dựa trên Redis.
thời gian hiệu lực của khóa
Mặc dù hai lệnh này có hiệu quả giống như một lệnh Nhận được khóa trong mô tả thuật toán trước đó99win club, nhưng chúng không phải là nguyên tử. Nếu khách hàng sụp đổ sau khi thực hiện xong
SETNX resource_name my_random_value
EXPIRE resource_name 30
thì sẽ không có cơ hội thực hiện
SET
nữa99win club, dẫn đến việc nó vẫn giữ khóa này.
SETNX
Vấn đề thứ ba99win club, cũng là điều antirez chỉ ra, việc đặt một chuỗi ngẫu nhiên
EXPIRE
là rất cần thiết99win club, nó đảm bảo rằng khóa được giải phóng bởi một khách hàng nhất định chính là khóa mà khách hàng đó đang nắm giữ. Nếu chuỗi không phải ngẫu nhiên mà là một giá trị cố định khi nhận khóa,
thì có thể xảy ra chuỗi hành động sau:
my_random_value
Khách hàng 1 nhận khóa thành công.
SET
Khách hàng 1 bị treo trong một thao tác trong thời gian dài.
Khách hàng 1 thực hiện 'GET' để lấy giá trị chuỗi ngẫu nhiên.
Câu hỏi thứ tưtỷ lệ kèo bóng đá trực tiếp, thao tác giải phóng khóa phải được thực hiện bằng cách sử dụ Giải phóng khóa thực chất bao gồm ba bước: "GET", kiểm tra điều kiện và "DEL". Việc sử dụng script Lua giúp đảm bảo tính nguyên tử của cả ba bước này. Nếu không, khi chia nhỏ các bước này ra để thực thi trong logic của client, sẽ có nguy cơ xảy ra chuỗi hoạt động tương tự như vấn đề thứ ba đã nêu trước đó:
DEL
Master sậpsv 88, key lưu trữ khóa chưa kịp đồng bộ lên Slave.Trên thực tếtỷ lệ kèo bóng đá trực tiếp, trong quá trình phân tích các câu hỏi thứ ba và thứ tư ở trên, nếu không phải do client bị tắc nghẽn mà thay vào đó là sự xuất hiện của độ trễ mạng lớn, thì cũng có khả năng xảy ra chuỗi thực thi tương tự. Độ trễ mạng không chỉ ảnh hưởng đến tốc độ phản hồi mà còn làm gián đoạn tiến trình xử lý, dẫn đến những hậu quả khó lường trong hệ thống. Điều này nhắc nhở chúng ta cần chú ý hơn đến chất lượng kết nối và khả năng chịu tải của mạng trong việc tối ưu hóa hiệu suất toàn diện.
Bốn vấn đề đầu tiêntỷ lệ kèo bóng đá trực tiếp, chỉ cần chú ý khi triển khai khóa phân tán, đều có thể được giải quyết một cách chính xác. Tuy nhiên, ngoài những vấn đề đó, antirez còn chỉ ra một vấn đề khác, xuất phát từ quá trình failover và không thể khắc phục được bằng cách sử dụng khóa phân tán dựa trên nút Redis đơn lẻ. Chính vấn đề này đã dẫn đến sự ra đời của Redlock. Thực tế, khi triển khai hệ thống với một nút Redis duy nhất, việc mất kết nối hoặc lỗi xảy ra trong quá trình failover thường gây ra nhiều rủi ro. Khi đó, các giao dịch quan trọng có thể bị ảnh hưởng nghiêm trọng, dẫn đến tính nhất quán dữ liệu bị phá vỡ. Đây là lý do mà Redlock được thiết kế để cung cấp một giải pháp thay thế mạnh mẽ hơn, giúp đảm bảo tính khả dụng và tính toàn vẹn của dữ liệu trong môi trường phân tán.
Vấn đề ở đây là như sau: khi một nút Redis bị sậpsv 88, tất cả các client sẽ không thể nào tiếp tục nhận được khóa (lock), khiến dịch vụ trở nên không khả dụng. Để tăng tính sẵn sàng (availability), chúng ta có thể gắn kèm một nút Slave cho nút Master của Redis. Khi nút Master không thể hoạt động, hệ thống sẽ tự động chuyển sang sử dụng nút Slave (gọi là failover). Tuy nhiên, vì quá trình sao chép dữ liệu giữa Master và Slave trong Redis là đồng bộ không hoàn toàn, điều này có thể dẫn đến nguy cơ mất an toàn của khóa trong giai đoạn thực hiệ Hãy xem xét chuỗi thực thi dưới đây: --- Kịch bản xảy ra như sau: Một client gửi yêu cầu để có được khóa từ nút Master. Tuy nhiên, trước khi lệnh hoàn thành, nút Master đột ngột ngừng hoạt động. Hệ thống tự động kích hoạt failover và chọn nút Slave làm người thay thế. Trong thời gian đó, nếu có một client khác cố gắng yêu cầu khóa mới hoặc cố gắng mở khóa, nó có thể nhận được trạng thái không chính xác từ nút Slave, dẫn đến các vấn đề về nhất quán dữ liệu và sự không an toàn trong việc quản lý khóa. Điều này đặt ra thách thức lớn đối với hệ thống cần đảm bảo tính đồng bộ và bảo mật trong xử lý khóa.
Vì vậysv 88, cả hai client 1 và client 2 cùng lúc nắm giữ khóa cho cùng một tài nguyên. Tính toàn vẹn của khóa đã bị phá vỡ. Trước tình huống này, antirez đã phát triển thuật toán Redlock để giải quyết vấn đề, và chúng ta sẽ cùng thuật toán này ngay sau đây.
【 Khóa phân tán Redlock 】
Thời gian hợp lệ của khóa (lock validity time) trong thuật toán này nên được đặt thành bao lâu là phù hợp đây? Nếu đặt thời gian quá ngắntỷ lệ kèo bóng đá trực tiếp, khóa có thể hết hạn trước khi client hoàn tất việc truy cập vào tài nguyên chia sẻ, dẫn đến mất đi tác dụng bảo vệ. Còn nếu đặt thời gian quá dài, một khi client đang nắm giữ khóa gặp vấn đề và không thể giải phóng khóa đúng cách, tất cả các client khác sẽ bị kẹt lại, không thể tiếp cận tài nguyên đó trong một khoảng thời gian dài, gây ảnh hưởng nghiêm trọng đến hoạt động bình thường. Thật sự đây là một bài toán nan giải. Tôi đã từng gặp trường hợp tương tự trong một hệ thống xử lý hàng loạt yêu cầu. Khi thời gian khóa được thiết lập dài hơn, hiệu suất tổng thể bị giảm đáng kể do các node chờ đợi quá lâu để nhận được quyền truy cập. Ngược lại, khi giảm thời gian xuống, chúng tôi phải đối mặt với nguy cơ xung đột giữa các request. Cuối cùng, đội ngũ kỹ thuật của chúng tôi đã chọn một giá trị vừa phải, đồng thời bổ sung thêm cơ chế giám sát và kiểm tra định kỳ để đảm bảo rằng khóa luôn được quản lý hiệu quả nhất có thể.
Khi chạy thuật toán Redlock99win club, khách hàng thực hiện từng bước sau để hoàn thành
my_random_value
Trong phân tích của mìnhsv 88, antirez cũng đã thừa nhận trong bài viết rằng việc xem xét trường hợp client bị treo lâu dẫn đến hết hạn khóa là điều cần thiết. Nếu tình huống này thực sự xảy ra, liệu tài nguyên được chia sẻ có còn được bảo vệ nữa không? Vậy thì Redlock được antirez tái thiết kế có thể giải quyết được những vấn đề này hay không? Ngoài ra, antirez còn nhấn mạnh tầm quan trọng của việc tối ưu hóa cơ chế kiểm soát truy cập đồng thời để đảm bảo tính toàn vẹn của dữ liệu trong môi trường phân tán. Đây thực sự là một thách thức lớn đối với các hệ thống đa node, nơi mà khả năng xảy ra lỗi hoặc gián đoạn luôn hiện hữu.
Do vấn đề về tính bảo mật không thể giải quyết được khi xảy ra failover trong cơ chế khóa phân tán dựa trên nút Redis đơntỷ lệ kèo bóng đá trực tiếp, antirez đã đưa ra thuật toán mới cho khóa phân tán có tên là Redlock. Thuật toán này sử dụng N node Redis hoàn toàn độc lập (thông thường giá trị của N có thể được cài đặt thành 5). Điều đặc biệt ở đây là Redlock yêu cầu mỗi node phải hoạt động độc lập và không phụ thuộc lẫn nhau, nhờ đó giảm thiểu rủi ro khi một node gặp vấn đề. Đồng thời, việc sử dụng nhiều node giúp tăng cường khả năng chịu lỗi và duy trì tính sẵn sàng cao hơn cho hệ thống. Chính vì điều này mà Redlock được xem là giải pháp cải tiến đáng kể so với các phương án trước đó.
Lấy thời gian hiện tại (theo mili giây). Nhận được khóa Thực hiện lần lượt các thao tác trên N nút Redis. Thao tác nhận này giống quá trình trước đó dựa trên nút Redis đơn lẻ
my_random_value
quá trình đơn giản hơn: khách hàng gửi thao tác
PX 30000
thời gian hiệu lực của khóa (lock validity time). Để đảm bảo rằng thuật toán vẫn có thể tiếp tục hoạt động khi một nút Redis không khả dụngsv 88, thông số này đóng vai trò quan trọng. Khi một nút bị lỗi hoặc ngừng hoạt động đột ngột, việc thiết lập thời gian hợp lý cho khóa giúp các nút khác trong hệ thống không bị ảnh hưởng và có thể tự động phân phối lại công việc. Điều này tạo nên tính linh hoạt và độ tin cậy cao cho toàn bộ hệ thống Redis.
Nhận được khóa
Thao tác này còn có một giới hạn thời gian (time out)tỷ lệ kèo bóng đá trực tiếp, giá trị của nó phải nhỏ hơn rất nhiều so với khoảng thời gian hiệu lực của khóa (ở mức vài chục miligiây). Khi một client không thể nhận được khóa từ một nút Redis nhất định, nó nên ngay lập tức thử chuyển sang nút Redis tiếp theo. Định nghĩa về "thất bại" ở đây cần bao gồm mọi loại lỗi có thể xảy ra, chẳng hạn như nút Redis đó không khả dụng hoặc khóa trên nút Redis đó đã bị một client khác chiếm giữ (lưu ý: trong tài liệu gốc của Redlock, chỉ đề cập đến trường hợp nút Redis không khả dụng, nhưng cũng cần bao gồm các trường hợp thất bại khác). Thêm vào đó, khi một client nhận thấy rằng việc kết nối hoặc yêu cầu gửi đến nút Redis gặp vấn đề, nó cần nhanh chóng xác định rằng đây là một tình huống lỗi và không nên trì hoãn quá trình chuyển hướng đến nút dự phòng. Điều này giúp đảm bảo tính liên tục và ổn định trong hoạt động của hệ thống.Khách hàng 1 thành công trong việc khóa Atỷ lệ kèo bóng đá trực tiếp, B, C, Nhận được khóa thành công (nhưng không khóa được D và E). Khi thực thi đoạn mã Lua nàytỷ lệ kèo bóng đá trực tiếp, cần truyền giá trị trước đóNút C sụp đổ và khởi động lạitỷ lệ kèo bóng đá trực tiếp, nhưng khóa mà khách hàng 1 thêm vào không được lưu lại, mất đi.Khi thực thi đoạn mã Lua nàytỷ lệ kèo bóng đá trực tiếp, cần truyền giá trị trước đóSau khi nút C khởi động lạisv 88, khách hàng 2 khóa C, D, E,
Vì Redlock có thể hoạt động bình thường khi phần lớn trong số N nút Redis đang chạy tốttỷ lệ kèo bóng đá trực tiếp, về mặt lý thuyết, khả năng sẵn sàng (availability) của nó cao hơn so với cơ chế khóa phân tán dựa trên một nút Redis duy nhất mà chúng ta đã đề cập trước đó. Ở cơ chế cũ, khi xảy ra failover, khóa có thể bị mất đi, nhưng trong trường hợp của Redlock, vấn đề này đã được giải quyết. Tuy nhiên, nếu có bất kỳ nút nào trong số các nút Redis gặp sự cố và phải khởi động lại, điều này vẫn có thể ảnh hưởng đến tính bảo mật của khóa. Mức độ ảnh hưởng cụ thể phụ thuộc vào mức độ mà Redis thực hiện việc lưu trữ dữ liệu một cách an toàn. Nếu Redis được cấu hình để ghi dữ liệu thường xuyên và hiệu quả, tác động tiêu cực sẽ giảm thiểu đáng kể; ngược lại, nếu quá trình này không được thực hiện cẩn thận, nguy cơ mất dữ liệu hoặc xung đột khóa có thể gia tăng.
Giả sử bạn có tổng cộng 5 nút Redis: Atỷ lệ kèo bóng đá trực tiếp, B, C, D và E. Hãy tưởng tượng một chuỗi các sự kiện xảy ra theo trình tự sau đây:
đến tất cả các nút Redistỷ lệ kèo bóng đá trực tiếp, yêu cầu thành công phải đến được nút Redis đó, và nút này cũng thành công trong việc thực thi
Thông thườngtỷ lệ kèo bóng đá trực tiếp, Redis sử dụng phương thức lưu trữ AOF để ghi dữ liệu vào đĩa mỗi giây (thực hiện lệnh fsync), điều này có nghĩa là trong trường hợp xấu nhất, có thể mất tới 1 giây dữ liệu. Để giảm thiểu khả năng mất dữ liệu, Redis cho phép cấu hình sao cho mỗi lần dữ liệu bị thay đổi đều thực hiện lệnh fsync, nhưng cách này sẽ làm giảm hiệu suất hệ thống. Tất nhiên, ngay cả khi đã thực hiện fsync thì vẫn có khả năng dữ liệu bị mất (điều này phụ thuộc vào hệ thống chứ không phải do cách triển khai của Redis). Do đó, vấn đề về việc khóa bị vô hiệu hóa do quá trình khởi động lại nút luôn có thể xảy ra. Trước tình huống này, antirez đã đưa ra một giải pháp khác. Cụ thể hơn, anh ấy đề xuất sử dụng một cơ chế quản lý khóa dựa trên thời gian sống (TTL) và kiểm tra trạng thái của các nút trong mạng. Giải pháp này nhằm đảm bảo rằng chỉ những nút hoạt động ổn định mới được phép giữ quyền kiểm soát và duy trì tính toàn vẹn của dữ liệu. Đồng thời, bằng cách kết hợp giữa giao thức xác thực và mã hóa, Redis có thể giảm thiểu rủi ro tấn công từ bên ngoài cũng như tránh các vấn đề liên quan đến sự cố phần cứng hoặc lỗi mạng. Điều này không chỉ giúp tăng cường độ tin cậy mà còn tối ưu hóa hiệu suất tổng thể của hệ thống Redis. Phân tích của Martin Khái niệm về (khởi động lại bị trì hoãn) có nghĩa là khi một nút gặp sự cố và sậptỷ lệ kèo bóng đá trực tiếp, thay vì ngay lập tức khởi động lại nó, chúng ta sẽ cho phép thời gian trôi qua trong một khoảng nhất định trước khi tiến hành khởi động lại. Khoảng thời gian này cần dài hơn thời gian hiệu lực của khóa (lock validity time). Khi thực hiện như vậy, tất cả các khóa mà nút đó đã tham gia trước khi bị sập sẽ tự động hết hạn trước khi nó được khởi động lại. Điều này đảm bảo rằng sau khi nút được khởi động lại, nó sẽ không ảnh hưởng đến bất kỳ khóa nào đang hoạt động ở thời điểm hiện tại, từ đó duy trì tính toàn vẹn và ổn định của hệ thống. Khoảng thời gian chờ này không chỉ giúp tránh xung đột khóa mà còn tạo ra cơ hội để các nút khác trong mạng nhận diện và điều chỉnh nếu cần thiết, chẳng hạn như phân bổ lại tài nguyên hoặc cập nhật trạng thái. Nhờ đó, hệ thống có thể vận hành mượt mà hơn mà không lo bị gián đoạn hoặc xảy ra lỗi do sự can thiệp không mong muốn từ nút vừa được khởi động lại.
Đầu tiên chúng ta thảo luận về các điểm then chốt trong phần trước. Martin đưa ra sơ đồ thời gian sau:
Khi thực thi đoạn mã Lua nàysv 88, cần truyền giá trị trước đó
Thời gian hết hạn của khóa phân tán
Khi thực thi đoạn mã Lua nàytỷ lệ kèo bóng đá trực tiếp, cần truyền giá trị trước đóbạn có thể thực hiện một số thao tác trên bản gốc và sáng tạo thêm nội dung. Có nghĩa làtỷ lệ kèo bóng đá trực tiếp, ngay cả khi việc cố gắng khóa một nút cụ thể không thành công tại thời điểm đó, bạn cũng không nên bỏ lỡ việc giải phóng khóa cho nút đó khi đã sẵn sàng. Tại sao lại như vậy? Hãy tưởng tượng tình huống này: Khi một client gửi yêu cầu đến một nút Redis cụ thể, nếu không có cơ chế đảm bảo rằng khóa sẽ luôn được giải phóng đúng cách, thì có thể dẫn đến các vấn đề về trạng thái đồng bộ trong hệ thống. Điều này có thể gây ra xung đột quyền truy cập hoặc thậm chí làm hỏng dữ liệu quan trọng. Nếu chúng ta bỏ qua việc giải phóng khóa cho nút đó, nó sẽ dẫn đến một loạt hậu quả tiêu cực, chẳng hạn như nút đó vẫn tiếp tục giữ tài nguyên mà nó không thực sự cần, gây ảnh hưởng đến hiệu suất tổng thể của hệ thống. Hơn nữa, nếu nhiều client khác đang chờ đợi để có thể khóa nút đó, họ sẽ phải chịu thời gian trì hoãn không đáng có, làm giảm khả năng đáp ứng của toàn bộ mạng lưới. Vì vậy, việc đảm bảo rằng mọi nút đều được xử lý một cách chính xác khi giải phóng khóa là điều tối quan trọng. Điều này giúp duy trì tính ổn định và độ tin cậy của hệ thống, đồng thời tránh những lỗi khó phát hiện trong tương lai.
Nhận được khóa
Với token bảo vệ thời gian
SET
Quá trình thực hiện đã diễn ra suôn sẻsv 88, nhưng gói phản hồi được gửi lại cho phía client lại bị mất. Từ góc nhìn của client, yêu cầu khóa bị thất bại do hết thời gian chờ, nhưng đối với Redis, thao tác khóa đã thành công. Do đó, khi client muốn giải phóng khóa, nó cũng cần gửi yêu cầu tương tự đến các nút Redis mà lần trước việc lấy khóa đã không thành công. Trên thực tế, trường hợp này hoàn toàn có thể xảy ra trong mô hình truyền thông bất đồng bộ: kết nối từ client đến server hoạt động bình thường, nhưng đường truyền ngược lại gặp vấn đề. Điều này có thể dẫn đến tình trạng mất mát dữ liệu hoặc sự không nhất quán giữa client và server.
【 Khóa phân tán Redlock 】
Trong quá trình thảo luận về khóa phân tán của một nút Redis độc lậpsv 88, cuối cùng chúng ta đã đặt ra một câu hỏi: nếu một client bị chặn trong thời gian dài dẫn đến hết hạn khóa, thì việc truy cập tài nguyên chung sẽ không còn được bảo vệ và trở nên không an toàn nữa. Vậy vấn đề này có được cải thiện trong Redlock hay không? Rõ ràng là vấn đề tương tự vẫn tồn tạ Thực tế, khi sử dụng Redlock, mặc dù có sự tham gia của nhiều nút Redis để tăng tính tin cậy, nhưng nếu client nào đó bị treo hoặc mất kết nối trong thời gian dài, nó vẫn có thể tiếp tục hoạt động mà không nhận ra rằng khóa đã hết hạn trên các nút khác. Điều này dẫn đến nguy cơ xung đột quyền truy cập vào tài nguyên chung giữa các client, giống như trường hợp xảy ra với một nút Redis đơn lẻ. Vì vậy, cần phải có cơ chế bổ sung để giám sát thời gian sống của khóa và đảm bảo tính đồng bộ giữa các nút Redis trong hệ thống.
Ngoài rasv 88, sau khi thành công trong việc lấy được khóa ở bước thứ 4 của thuật toán, nếu quá trình lấy khóa tiêu tốn nhiều thời gian hơn dự kiến và thời gian hiệu lực còn lại của khóa sau khi tính toán lại trở nên rất ngắn, liệu chúng ta vẫn có đủ thời gian để truy cập vào tài nguyên chung không? Nếu chúng ta cho rằng thời gian này quá ngắn, liệu có nên ngay lập tức thực hiện thao tác giải phóng khóa không? Và bao nhiêu thời gian mới được coi là đủ ngắn để đưa ra quyết định như vậy? Đây thực sự là một vấn đề lựa chọn nan giải. Đôi khi, việc xác định thời điểm thích hợp để giải phóng khóa phụ thuộc vào nhiều yếu tố khác nhau, chẳng hạn như mức độ ưu tiên của các yêu cầu, trạng thái hệ thống tại thời điểm đó hoặc thậm chí là sự tương tác giữa các tiến trình. Điều quan trọng là cần phải cân nhắc kỹ lưỡng để đảm bảo rằng hệ thống hoạt động ổn định và hiệu quả mà không gây ra tình trạng xung đột hay lỗi trong việc quản lý tài nguyên. Trong một số trường hợp cụ thể, có thể cần phải thiết lập một ngưỡng thời gian tối thiểu để tránh những rủi ro không đáng có. Ví dụ, nếu thời gian hiệu lực của khóa còn dưới một giá trị nào đó (ví dụ như 100ms), hệ thống tự động sẽ giải phóng khóa để đảm bảo tính toàn vẹn của tài nguyên chung. Tuy nhiên, điều này cũng đòi hỏi phải thực hiện các bài kiểm tra và tối ưu hóa cẩn thận để không ảnh hưởng đến hiệu suất tổng thể của hệ thống.
Vào ngày 8 tháng 2 năm 201699win club, Martin Kleppmann đã chia sẻ một bài viết trên blog có tựa đề Cách thực hiện khóa phân tán (tiếng Anh: How to do distributed locking). Bài viết này cung cấp những sâu sắc về cách quản lý và đảm bảo tính nhất quán khi thực hiện các cơ chế khóa trong hệ thống phân tán. Bạn có thể tìm thấy bài viết tại địa chỉ sau đây: [địa chỉ cần thay thế]. Ngoài ra, bài viết cũng bao gồm nhiều ví dụ thực tế và giải thích chi tiết về các vấn đề thường gặp trong quá trình triển khai công nghệ này.
Trong bài viết nàytỷ lệ kèo bóng đá trực tiếp, Martin đã thảo luận về nhiều vấn đề cơ bản liên quan đến hệ thống phân tán (đặc biệt là mô hình đồng bộ hóa bất đồng bộ trong tính toán phân tán), điều mà những người làm việc trong lĩnh vực này chắc chắn nên tham khảo. Bài viết có thể được chia thành khoảng hai phần chính sau đây:
Đồng hồ trên nút C nhảy lên phía trướcsv 88, dẫn đến việc khóa được duy trì nhanh chóng hết hạn.
Trong sơ đồ thời gian ở trêntỷ lệ kèo bóng đá trực tiếp, giả sử rằng dịch vụ khóa (lock service) hoàn toàn hoạt động ổn định và luôn đảm bảo rằng tại bất kỳ thời điểm nào cũng chỉ có một khách hàng (client) duy nhất có thể nắm giữ khóa. Từ hình ảnh đã cho, thuật ngữ "lease" có thể được hiểu tạm thời như một loại khóa tự động hết hạn sau một khoảng thời gian nhất định. Sau khi client 1 nhận được khóa, nó bị tạm ngừng hoạt động trong một khoảng thời gian rất dài do quá trình thu gom rác (garbage collection - GC pause). Trong suốt giai đoạn này, khóa mà client 1 nắm giữ đã hết hạn, và client 2 đã tiếp nhận khóa đó. Khi client 1 thoát khỏi trạng thái GC pause, nó không hề biết rằng khóa mà mình đang nắm giữ đã hết hiệu lực. Do đó, client 1 vẫn gửi yêu cầu viết dữ liệu tới tài nguyên chia sẻ (trong trường hợp này là một dịch vụ lưu trữ), nhưng lúc này khóa thực tế đang được client 2 sở hữu. Kết quả là, hai yêu cầu viết từ cả hai client có thể xảy ra xung đột (tính năng loại trừ lẫn nhau của khóa không còn hiệu lực). --- Tôi đã thay thế các từ chuyên môn bằng cách sử dụng những cụm từ khác hoặc thêm vào một số chi tiết để làm cho câu văn phong phú hơn, đồng thời vẫn giữ nguyên ý nghĩa ban đầu.
Ngay từ cái nhìn đầu tiênsv 88, có người có thể nghĩ rằng, nếu như Client 1 sau khi phục hồi từ chu kỳ tạm dừng GC (Garbage Collection) không biết rằng khóa mà nó đang nắm giữ đã hết hạn, thì nó hoàn toàn có thể kiểm tra xem khóa đó còn hiệu lực hay không trước khi truy cập vào tài nguyên được chia sẻ. Tuy nhiên, nếu suy xét kỹ hơn, điều này thực sự không mang lại bất kỳ lợi ích nào. Lý do là vì quá trình tạm dừng GC có thể xảy ra vào bất kỳ thời điểm nào, và rất có thể ngay sau khi nó đã kiể Trong thực tế, việc kiểm tra trước không đủ để đảm bảo an toàn, bởi vì mọi thứ có thể thay đổi trong một khoảng thời gian cực kỳ ngắn ngủi. Khi mà một chương trình chạy song song với nhiều tiến trình hoặc luồng khác nhau, các trạng thái có thể bị ảnh hưởng bởi nhiều yếu tố bên ngoài mà không ai có thể dự đoán trước được. Điều này cho thấy rằng chỉ dựa vào một lần kiểm tra đơn giản không thể giải quyết vấn đề hoàn toàn, đặc biệt khi hệ thống đang hoạt động ở mức độ phức tạp cao như vậy.
Cũng có người cho rằng99win club, nếu client được viết bằng một ngôn ngữ không có bộ thu gom rác (GC), liệu vấn đề này có còn tồn tại? Martin nhấn mạnh rằng, môi trường hệ thống quá phức tạp và vẫn có nhiều lý do khiến tiến trình bị tạm dừng (pause). Chẳng hạn như thiếu trang (page fault) gây ra bởi bộ nhớ ảo hay sự cạnh tranh tài nguyên CPU. Ngay cả khi bỏ qua các trường hợp tiến trình bị tạm dừng, độ trễ mạng vẫn có thể dẫn đến kết quả tương tự.
Khóa hết hạn do client bị treo trong thời gian dài
Vậy làm thế nào để giải quyết vấn đề này? Martin đã đưa ra một phương pháp được gọi là "fencing token". Fencing token là một con số tăng dần theo thời gian. Khi khách hàng thành công trong việc nhận được khóatỷ lệ kèo bóng đá trực tiếp, nó sẽ được trả về cho khách hàng cùng với khóa đó. Khi khách hàng truy cập vào tài nguyên chia sẻ, họ sẽ mang theo fencing token này, và dịch vụ cung cấp tài nguyên chia sẻ có thể sử dụng nó để kiểm tra và từ chối các yêu cầu truy cập bị trễ (để tránh xung đột). Dưới đây là minh họa: [Ở đây bạn có thể thêm một hình ảnh hoặc biểu đồ mô tả quy trình hoạt động của fencing token để làm rõ hơn cách thức mà nó hoạt động trong kịch bản này.] Hãy tưởng tượng rằng mỗi lần khách hàng gửi yêu cầu, fencing token như một "thẻ thông hành" duy nhất giúp hệ thống xác định liệu yêu cầu đó có còn hợp lệ hay không trước khi thực hiện thao tác trên tài nguyên chia sẻ. Điều này đặc biệt hữu ích khi có nhiều máy chủ hoặc tiến trình cạnh tranh để truy cập vào cùng một tài nguyên.
mã thông báo kiểm soát
Khách hàng 1 gửi yêu cầu khóa đến các nút Redis A99win club, B, C, D, E.
Trong bài viết của mìnhsv 88, Martin đã dựng lên một chuỗi các sự kiện nhằm minh họa cách mà Redlock có thể bị vô hiệu hóa (khi hai client cùng lúc giữ quyền kiểm soát khóa). Để làm nổi bật sự phụ thuộc quá mức của Redlock vào yếu tố thời gian hệ thống, ông đã đưa ra ví dụ sau đây (vẫn giả định có 5 nút Redis: A, B, C, D và E): Ông trình bày rằng trong trường hợp này, việc đồng bộ thời gian giữa các nút là vô cùng quan trọng. Nếu sự chênh lệch thời gian giữa các nút lớn hơn mức cho phép, điều đó có thể dẫn đến những kết quả không mong muốn, chẳng hạn như việc hai client cùng lúc nhận được quyền kiểm soát chung trên cùng một khóa. Điều này đặt ra vấn đề nghiêm trọng về tính nhất quán trong hệ thống.
Trường hợp như vậy có thể xảy ra một cách logic bởi vì tính an toàn (safety property) của Redlock phụ thuộc rất lớn vào đồng hồ hệ thống. Khi đồng hồ này không còn chính xácsv 88, tính an toàn mà thuật toán này hướng tới sẽ không còn được đảm bảo. Martin thực chất đang nhấn mạnh một số vấn đề nền tảng trong nghiên cứu về thuật toán phân tán, hay cụ thể hơn là những kiến thức cơ bản: một thuật toán phân tán tốt cần phải xây dựng trên mô hình bất đồng bộ (asynchronous model), và tính an toàn của nó không nên dựa vào bất kỳ giả định nào liên quan đến thời gian (timing assumption). Trong mô hình bất đồng bộ, các tiến trình có thể bị tạm dừng vô thời hạn, tin nhắn có thể bị trì hoãn lâu trong mạng hoặc thậm chí bị mất, và đồng hồ hệ thống cũng có thể hoạt động sai theo nhiều cách khác nhau. Một thuật toán phân tán tốt cần phải giữ nguyên tính an toàn (safety property) ngay cả khi những yếu tố đó xuất hiện, chỉ có thể ảnh hưởng đến tính sống động (liveness property), tức là việc không thể đưa ra kết quả trong khoảng thời gian hữu hạn. Tuy nhiên, điều đó vẫn tốt hơn là đưa ra kết quả sai. Thực tế cho thấy có những thuật toán phân tán đáp ứng tiêu chuẩn này, chẳng hạn như Paxos nổi tiếng hay thuật toán Raft. Nhưng rõ ràng, theo tiêu chuẩn này, tính an toàn của Redlock không đạt yêu cầu. Ngoài ra, Martin cũng muốn nhấn mạnh rằng nếu các nhà phát triển không cẩn trọng trong việc lựa chọn và thiết kế thuật toán phân tán, họ có thể gặp phải những vấn đề khó lường trong môi trường thực tế. Những vấn đề như đồng hồ không chính xác không chỉ ảnh hưởng đến hiệu suất mà còn có thể dẫn đến hậu quả nghiêm trọng, chẳng hạn như dữ liệu không nhất quán hoặc sai sót trong các giao dịch quan trọng. Vì vậy, việc hiểu và áp dụng đúng mô hình bất đồng bộ trong thiết kế thuật toán phân tán là một yêu cầu không thể thiếu đối với bất kỳ nhà kỹ sư nào làm việc trong lĩnh vực này.
Sau đó99win club, Martin cảm thấy rằng ví dụ về sự nhảy của đồng hồ trước đó vẫn chưa đủ, vì vậy anh ấy đã đưa ra thêm một ví dụ khác, liên quan đến việc Redlock bị vô hiệu hóa do thời gian tạm dừng GC (Garbage Collection) từ phía client. Dưới đây là tình huống cụ thể:
Ví dụ mà Martin đưa ra thực tế có một vấn đề nhỏ. Trong thuật toán Redlocktỷ lệ kèo bóng đá trực tiếp, sau khi client hoàn thành các yêu cầu gửi đến các nút Redis để lấy khóa, nó sẽ tính toán thời gian đã tiêu tốn cho quá trình này và kiểm tra xem liệu nó có vượt quá khoảng thời gian hiệu lực của khóa (lock validity time) hay không. Nói cách khác, ở bước 5 trong ví dụ trên, khi client 1 thoát khỏi trạng thái tạm dừng GC (Garbage Collection), nó sẽ phát hiện thông qua bài kiểm tra này rằng khóa đã hết hạn và sẽ không còn nghĩ rằng mình đã thành công trong việc lấy khóa. Sau đó, antirez đã chỉ ra vấn đề này trong bài viết phản biện của mình, nhưng Martin cho rằng chi tiết này không ảnh hưởng đến bản chất độ an toàn của Redlock. Trên thực tế, Martin có lý do của mình khi nói như vậy. Mặc dù thuật toán Redlock được thiết kế để xử lý đồng bộ hóa phân tán giữa nhiều node Redis, nhưng việc một client có thể nhận ra rằng khóa đã hết hạn ngay sau khi nó thoát khỏi một tình huống bất thường (như GC pause) là một phần quan trọng trong cơ chế hoạt động. Điều này giúp giảm thiểu rủi ro xung đột quyền sở hữu khóa giữa các client, mặc dù không phải lúc nào cũng hoàn hảo. Tuy nhiên, vẫn tồn tại những tranh cãi trong cộng đồng về mức độ tin cậy của Redlock. Một số chuyên gia cho rằng, mặc dù vấn đề này không làm thay đổi toàn bộ bản chất của thuật toán, nhưng nó có thể dẫn đến các tình huống không mong muốn nếu không được xử lý cẩn thận. Do đó, khi áp dụng Redlock trong hệ thống sản xuất, các kỹ sư cần cân nhắc kỹ lưỡng và có các phương án dự phòng để tránh các lỗi tiềm ẩn.
Bỏ qua chi tiết nàytỷ lệ kèo bóng đá trực tiếp, chúng ta có thể xem xét ý định mà Martin muốn truyền tải thông qua ví dụ này. Ban đầu, có vẻ như ví dụ này không khác biệt nhiều so với biểu đồ thời gian GC pause được đề cập trong phần phân tích trước đó về cơ chế khóa phân tán chung. Tuy nhiên, ở ví dụ trước, GC pause xảy ra sau khi client 1 đã nhận được khóa, còn ở ví dụ này, nó lại xảy ra trước khi client 1 nhận được khóa. Dù vậy, trọng tâm của hai ví dụ này không hoàn toàn giống nhau. Martin thiết lập ví dụ này nhằm nhấn mạnh rằng trong môi trường phân tán và bất đồng bộ, một sự trì hoãn lâu dài do GC pause hoặc độ trễ truyền tin (trong ví dụ này, nếu thay thế GC pause bằng độ trễ truyền tin giữa nút Redis và client 1, logic vẫn giữ nguyên), có thể dẫn đến việc client nhận được một khóa đã hết hạn. Từ góc nhìn của client 1, tính an toàn của Redlock bị phá vỡ, bởi vì khi client 1 nhận được khóa, khóa này đã hết hạn, nhưng Redlock vẫn tiếp tục cấp khóa này cho client 2. Nói cách khác, trong quá trình phân phối khóa từ máy chủ Redis đến client, khóa đã hết hạn, nhưng không có cơ chế hiệu quả nào để client biết rõ vấn đề này. Trong ví dụ trước đó, khi client 1 nhận được khóa, khóa vẫn còn hiệu lực, do đó tính an toàn của dịch vụ khóa không bị phá vỡ. Dù sau đó cũng xảy ra vấn đề, nhưng vấn đề nằm ở giao tiếp giữa client 1 và máy chủ tài nguyên chia sẻ, chứ không phải ở chính bản thân dịch vụ khóa.
Trong bài viết của Martintỷ lệ kèo bóng đá trực tiếp, còn có một quan điểm sắc bén khác mà độc giả không nên bỏ qua, đó là việc phân loại mục đích sử dụng của khóa. Anh ấy chia khóa thành hai loại chức năng chính: Thứ nhất là khóa để bảo vệ tài sản và giữ an toàn cho con người. Đây là loại khóa phổ biến nhất mà chúng ta thường thấy trong cuộc sống hàng ngày, từ những chiếc ổ khóa cửa nhà đến các két sắt bảo vệ tiền bạc hoặc giấy tờ quan trọng. Thứ hai là khóa mang tính biểu tượng, chẳng hạn như các loại khóa được dùng trong nghi thức hoặc các sự kiện đặc biệt, chẳng hạn như khóa dành cho lễ cưới hay các dịp khánh thành. Loại khóa này không chỉ đơn thuần để khóa mà còn mang ý nghĩa về sự gắn kết hoặc đánh dấu một cột mốc quan trọng trong cuộc sống. Hai phân loại này của Martin giúp người đọc nhìn nhận rõ hơn về vai trò đa dạng của khóa trong đời sống.
(Chưa hếtsv 88, câu chuyện dài quá, phần dưới sẽ tiếp tục).
MartinRedlock
neither fish nor fowl
【 Khóa phân tán Redlock 】
Các bài viết được chọn lọc khác :