Khóa phân tán dựa trên Redis có thực sự an toàn không? (phần trên)


Khóa phân tán Redis

Thực tếbầu cua, khoảng một năm trước, về vấn đề an ninh của Distributed Lock dựa trên Redis, trong cộng đồng các chuyên gia hệ thống phân tán, Martin Kleppmann và tác giả của Redis antirez Trước đó đã xảy ra một cuộc tranh luận. Vì tôi luôn quan tâm đến vấn đề nàytỉ lệ cược, nên cách đây không lâu, tôi đã dành thời gian nghiên cứu cẩn thận các tài liệu liên quan đến cuộc tranh luận đó. Cuộc tranh luận này diễn ra như sau: tác giả của Redis đã đưa ra một phương án mới được cải tiến hơn nhằm chuẩn hóa cách thức thực hiện bộ khóa phân tán dựa trên Redis, và phương án này được gọi là Redlock . Một ngày nọi9bet.com nhận 100k, Martin Kleppmann đã viết một bài báo blog phân tích những vấn đề về an ninh mà Redlock gặp phải. Sau đói9bet.com nhận 100k, tác giả của Redis ngay lập tức viết một bài trả lời blog Bạn có thể tranh luận lại phân tích của Martin. Tuy nhiêni9bet.com nhận 100k, Martin khẳng định vẫn giữ nguyên quan điểm ban đầu của mình. Ngay sau đó, vấn đề này đã gây ra một cuộc tranh luận sôi nổi trên Twitter và trang Hacker News, với sự tham gia của nhiều chuyên gia trong lĩnh vực hệ thống phân tán. Trên các nền tảng này, những ý kiến trái chiều liên tục được đưa ra, từ việc chỉ ra những điểm yếu trong lập luận của Martin cho đến việc ủng hộ cách tiếp cận mà anh ấy chọn. Một số người nhấn mạnh rằng việc hiểu rõ bản chất của vấn đề đòi hỏi phải xem xét toàn diện nhiều khía cạnh khác nhau, trong khi những người khác lại cho rằng Martin nên cân nhắc thêm dữ liệu mới trước khi đưa ra kết luận. Cuộc tranh luận không chỉ giới hạn ở lý thuyết, mà còn mở rộng sang thực tiễn, khi các chuyên gia chia sẻ kinh nghiệm thực tế về việc triển khai các hệ thống tương tự trong môi trường sản xuất. Điều này khiến cho chủ đề trở nên hấp dẫn hơn bao giờ hết, thu hút sự chú ý của cộng đồng công nghệ nói chung.

Đối với những ai quan tâm đến hệ thống phân tántỉ lệ cược, 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 sẽ 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, có thể được coi là một chuyên gia hàng đầu trong lĩnh vực hệ thống phân tán. Tuy nhiên, khi phân tích về các vấn đề liên quan đến khóa phân tán, các chuyên gia lại đưa ra những kết luận khác nhau, từ đó ta có thể thấy mức độ phức tạp của các vấn đề trong hệ thống phân tán. Thực tế, trong thiết kế hệ thống phân tán, thường xảy ra tình huống: nhiều ý tưởng ban đầu nghe có vẻ hoàn hảo, nhưng khi xem xét kỹ lưỡng hơn, chúng không phải lúc nào cũng hoàn toàn không có khuyết điểm. Điều này minh chứng cho sự thách thức và sự cần thiết phải luôn cẩn trọng trong quá trình phát triển hệ thống phân tán.

Tiếp theotỉ lệ cược, chúng ta sẽ lần lượt đi từ đầu đến cuối để xem lại và phân tích các quan điểm của tất cả các bên trong quá trình tranh luận này. Trong suốt hành trình đó, chúng ta sẽ cùng nhau những chi tiết kỹ thuật phức tạp ảnh hưởng đến tính bảo mật của hệ thống khóa phân tán - một chủ đề chắc chắn sẽ khiến bạn cảm thấy hứng thú. Đây là một câu chuyện khá dài, và trong đó không thể tránh khỏi việc lẩn quất vài tin đồn thú vị liên quan đến các nhà phát triển và sự kiện trong ngành công nghệ.

Thuật toán Redlock

Giống như những gì đã đề cập ở phần đầu bài viếti9bet.com nhận 100k, việc sử dụng Redis để triển khai một locks phân tán (Distributed Lock) đã được nhiều người thử nghiệm. Mục đích của việc xây dựng loại locks này là để quản lý việc truy cập đồng thời vào các tài nguyên chung một cách hiệu quả và an toàn. Ngoài ra, với sự phát triển nhanh chóng của hệ thống phân tán hiện đại, việc đảm bảo tính nhất quán khi nhiều máy chủ hoặc dịch vụ cùng lúc truy cập vào cùng một tài nguyên trở nên vô cùng quan trọng. Do đó, Redis, với khả năng xử lý nhanh chóng và độ tin cậy cao, đã trở thành một lựa chọn phổ biến cho giải pháp này.

Tuy nhiêntỉ lệ cược, mặc dù các cách triển khai này có xu hướng tương đồng về ý tưởng chung, nhưng ở chi tiết thực hiện lại hoàn toàn khác nhau. Đồng thời, mức độ bảo mật và tính khả dụng mà chúng cung cấp cũng không giống nhau. Do đó, Antirez - tác giả của Redis, đã đưa ra một giải pháp tốt hơn được gọi là Redlock, đây cũng được coi là hướng dẫn tiêu chuẩn chính thức từ Redis để quản lý khóa phân tán. Mô tả thuật toán của Redlock được đặt tại trang web chính thức của Redis:

Trước khi có Redlockbầu cua, cách thực hiện các khóa phân tán chủ yếu 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). Để hiểu rõ Redlock, chúng ta cần trước tiên làm rõ thuật toán cơ bản hoạt động với một nút Redis đơn lẻ, vì đây chính là nền tảng của Redlock. Việc hiểu được cách thức hoạt động của khóa phân tán dựa trên một nút Redis sẽ giúp bạn nắm bắt được các khái niệm cốt lõi. Điều này không chỉ tạo điều kiện thuận lợi cho việc triển khai mà còn giúp tối ưu hóa hiệu suất trong các hệ thống lớn. Redlock mang lại sự linh hoạt và độ tin cậy cao hơn so với giải pháp dựa trên một nút duy nhất, nhưng tất cả đều bắt đầu từ việc hiểu rõ nguyên lý cơ bản.

Khóa phân tán dựa trên nút Redis đơn

Đầu tiên, để Nhận khóa tỉ lệ cược, Redis client gửi lệnh sau đến nút Redis:

								
									SET resource_name my_random_value NX PX 30000

								

Nếu lệnh này được thực hiện thành côngtỉ lệ cược, client sẽ nhận được khóa, tiếp theo có thể Truy cập tài nguyên chung ; còn nếu lệnh không thành côngi9bet.com nhận 100k, điều đó 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 Chuỗi ngẫu nhiên này được tạo ra bởi clientbầu cua, và nó cần phải đảm bảo tính duy nhất trong một khoảng thời gian khá dài, bất kể các yêu cầu khóa từ tất cả các client khác nhau. Điều này giúp tránh xung đột và đảm bảo tính toàn vẹn khi nhiều client cùng hoạt động đồng thời.
  • NX cho thấy chỉ khi resource_name key tương ứng không tồn tại thì mới có thể SET Thành công. Điều này đảm bảo rằng chỉ có client gửi yêu cầu đầu tiên mới có thể nhận được khóatỉ lệ cược, trong khi các client khác sẽ không thể nào có được khóa cho đến khi nó được giải phóng. Trong khoảng thời gian đó, tất cả các client còn lại sẽ phải chờ đợi, tạo ra một cơ chế kiểm soát quyền truy cập chặt chẽ và hiệu quả.
  • PX 30000 Khóa này có thể tự động hết hạn sau 30 giây. Tất nhiênbầu cua, con số 30 giây chỉ là một ví dụ minh họa; phía client hoàn toàn có thể điều chỉnh thời gian hết hạn phù hợp với nhu cầu thực tế của mình. Việc linh hoạt trong việc đặt thời gian sẽ giúp tăng tính bảo mật và hiệu quả cho hệ thống.

Cuối cùngi9bet.com nhận 100k, sau khi client hoàn thành thao tác với tài nguyên chung, nó thực hiện đoạn mã Lua Redis sau đây để Giải phóng khóa

								if redis.call("get"bầu cua,KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

Khi đoạn mã Lua này được thực thibầu cua, cần truyền giá trị trước đó my_random_value giá trị tham sối9bet.com nhận 100k, và giá trị ARGV[1] làm tham số. resource_name giá trị tham sối9bet.com nhận 100k, và giá trị KEYS[1] Vấn đề thứ haibầu cua, bước đầu tiên

Đến đâyi9bet.com nhận 100k, thuật toán về khóa phân tán dựa trên nút Redis đơn đã được trình bày hoàn chỉnh. Có một số vấn đề quan trọng cần được phân tích sâu thêm. Trước hết, tính khả dụng của khóa trong trường hợp nút Redis gặp sự cố là điều cần phải xem xét kỹ lưỡng. Khi nút Redis bị lỗi, liệu các tiến trình khác có thể tiếp tục hoạt động mà không bị ảnh hưởng? Đây là một thách thức lớn khi triển khai khóa phân tán dựa trên Redis đơn. Thứ hai, vấn đề về thời gian sống (TTL - Time To Live) của khóa cũng cần được chú ý. Nếu TTL quá ngắn, có thể xảy ra tình trạng khóa bị giải phóng trước khi tác vụ hoàn thành. Ngược lại, nếu TTL quá dài, sẽ dẫn đến hiện tượng khóa bị giữ quá lâu, gây xung đột với các tiến trình khác. Cuối cùng, vấn đề cạnh tranh giữa các tiến trình khi khóa cũng cần được tối ưu hóa. Cần đảm bảo rằng chỉ có một tiến trình duy nhất nhận được khóa tại bất kỳ thời điểm nào, đồng thời giảm thiểu thời gian chờ đợi không cần thiết. Việc hiểu rõ và giải quyết các vấn đề này sẽ giúp đảm bảo tính ổn định và hiệu quả của thuật toán khóa phân tán dựa trên Redis đơn.

Đầu tiêni9bet.com nhận 100k, vấn đề quan trọng đầu tiên là khóa phải được thiết lập một khoảng thời gian hết hạn. Nếu không, khi một client nhận được khóa thành công nhưng gặp lỗi hoặc do hiện tượng phân chia mạng (network partition) khiến nó không thể liên lạc với nút Redis nữa, thì khóa sẽ vẫn tiếp tục tồn tại và các client khác sẽ không bao giờ có cơ hội để sở hữu nó. Antirez cũng nhấn mạnh điều này trong phần phân tích sau đó và gọi khoảng thời gian hết hạn này là thời gian hiệu lực của khóa (lock validity time). Client nào giữ khóa phải hoàn thành việc truy cập tài nguyên chung trong khoảng thời gian này. Ngoài ra, việc đặt thời gian hết hạn còn giúp đảm bảo tính công bằng giữa các client khác nhau, tránh tình trạng một client duy trì khóa quá lâu mà không giải phóng, gây cản trở cho các yêu cầu từ client khác. Điều này đặc biệt quan trọng trong môi trường làm việc với nhiều node và kết nối phức tạp như hệ thống phân tán.

bầu cua, nhiều bài viết trên mạng đã thực hiện nó dưới dạng hai lệnh Redis: Nhận khóa Mặc dù hai lệnh này và lệnh

								
									SETNX resource_name my_random_value
EXPIRE resource_name 30

								

mô tả trước đó có hiệu quả giống nhaui9bet.com nhận 100k, nhưng chúng không phải là nguyên tử. Nếu client sụp đổ sau khi thực hiện xong SET tỉ lệ cược, nó sẽ không có cơ hội thực hiện SETNX nữabầu cua, dẫn đến việc nó vẫn giữ khóa này. EXPIRE Vấn đề thứ batỉ lệ cược, cũng là điều mà antirez chỉ ra, việc đặt một chuỗi ngẫu nhiên

là rất cần thiếti9bet.com nhận 100k, nó đảm bảo rằng khóa mà client giải phóng phải là khóa mà chính nó đang nắm giữ. Nếu chuỗi không phải là ngẫu nhiên mà là giá trị cố định khi nhận khóa, my_random_value thì có thể xảy ra chuỗi thực thi như sau: SET Client 1 nhận khóa thành công.

  1. Client 1 bị tắc nghẽn trong một thời gian dài trong một hoạt động nào đó.
  2. Thời gian hết hạn đếntỉ lệ cược, khóa tự động được giải phóng.
  3. Client 2 nhận được khóa tương ứng với tài nguyên chung.
  4. Client 1 thoát khỏi trạng thái bị tắc nghẽnbầu cua, giải phóng khóa mà client 2 đang nắm giữ.
  5. Sau đótỉ lệ cược, khi client 2 truy cập tài nguyên chung, không có khóa nào để bảo vệ nó.

Client 1 truy cập tài nguyên chung.

Câu hỏi thứ tưbầu cua, thao tác giải phóng khóa phải được thực hiện bằng cách sử dụ Việc 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'. Sử dụng Lua script sẽ đảm bảo rằng cả ba bước này diễn ra một cách nguyên tử (atomic), tức là không bị gián đoạn hoặc xen kẽ bởi các tác vụ khác. Nếu không, khi thực hiện ba bước này trong logic của client, có thể xảy ra chuỗi hoạt động tương tự như vấn đề ở câu hỏi thứ ba trước đó: Imagine this scenario: Khi một client gửi yêu cầu để giải phóng khóa, nhưng giữa chừng nó gặp lỗi hoặc bị ngắt kết nối, dẫn đến việc chỉ thực hiện được một phần thao tác. Điều này có thể khiến trạng thái hệ thống trở nên không đồng nhất, chẳng hạn như khóa vẫn chưa được xóa hoàn toàn, nhưng dữ liệu đã bị thay đổi. Vì vậy, việc sử dụng Lua script là cách tốt nhất để tránh những tình huống như vậy và duy trì tính toàn vẹn của hệ thống.

  1. Client 1 bị tắc nghẽn trong một thời gian dài trong một hoạt động nào đó.
  2. Client 1 thực hiện 'GET' để lấy giá trị của chuỗi ngẫu nhiên.
  3. Client 1 kiểm tra giá trị chuỗi ngẫu nhiêntỉ lệ cược, so sánh với giá trị mong đợi.
  4. Client 1 bị tắc nghẽn trong một thời gian dài vì một lý do nào đó.
  5. Client 1 thoát khỏi trạng thái bị tắc nghẽntỉ lệ cược, thực hiện
  6. Client 2 nhận được khóa tương ứng với tài nguyên chung.
  7. Client 1 thoát khỏi trạng thái bị tắc nghẽntỉ lệ cược, giải phóng khóa mà client 2 đang nắm giữ.
  8. thao táctỉ lệ cược, giải phóng khóa mà client 2 đang nắm giữ. DEL Client 1 nhận được khóa từ Master.

Trên thực tếi9bet.com nhận 100k, trong quá trình phân tích các câu hỏi thứ ba và thứ tư đã đề cập, 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ó thể dẫn đến việc xảy ra chuỗi thực thi tương tự như vậy. Khi mạng gặp vấn đề về độ trễ, tín hiệu hoặc dữ liệu gửi đi sẽ mất nhiều thời gian hơn để đạt được đích, điều này có thể gây ra những tình huống khó kiểm soát trong tiến trình hoạt động của hệ thống.

Những vấn đề đầu tiên nàytỉ lệ cược, nếu bạn cẩn thận 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 điều đó, antirez còn chỉ ra một vấn đề khác, xuất phát từ quá trình failover và không thể xử lý đượ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 thực hiện failover, các nút Redis trong hệ thống có thể gặp phải tình huống không đồng bộ hoặc mất kết nối tạm thời, làm cho việc quản lý khóa trở nên phức tạp hơn. Điều này nhấn mạnh tầm quan trọng của việc tìm kiếm một giải pháp mạnh mẽ hơn để đảm bảo tính nhất quán và hiệu quả trong hệ thống phân tán. Redlock đã được thiết kế để giải quyết những hạn chế này, cung cấp một cơ chế an toàn và ổn định hơn cho việc quản lý khóa phân tán.

Có một vấn đề như sau: khi một nút Redis gặp sự cố và ngừng hoạt độngi9bet.com nhận 100k, tất cả các client sẽ không thể tiếp tục nhận được khóa (lock), khiến dịch vụ bị gián đoạn. Để tăng cường tính khả dụng, chúng ta có thể kết nối một nút Slave với nút Master của Redis. Khi nút Master không thể truy cập được, hệ thống sẽ tự động chuyển sang sử dụng nút Slave (failover). Tuy nhiên, do quá trình sao chép dữ liệu giữa Master và Slave trong Redis là đồng bộ, điều này có thể dẫn đến mất an toàn về khóa trong giai đoạn failover xảy ra. Hãy xem xét chuỗi thực thi sau đây: --- Trong trường hợp nút Master ngừng hoạt động, nếu một giao dịch quan trọng đang diễn ra tại thời điểm failover, nó có thể không được phản ánh chính xác trên nút Slave. Điều này dẫn đến nguy cơ hai hoặc nhiều client cùng nhận được cùng một khóa, gây ra xung đột dữ liệu. Vì vậy, cần phải đánh giá kỹ lưỡng cách hệ thống xử lý các kịch bản này để đảm bảo tính nhất quán và độ tin cậy. --- Vấn đề ở đây không chỉ liên quan đến việc mất khóa mà còn ảnh hưởng trực tiếp đến tính toàn vẹn của dữ liệu. Để giải quyết triệt để, có thể cân nhắc sử dụng Redis Sentinel hoặc Redis Cluster, những công cụ giúp cải thiện khả năng chịu lỗi và duy trì tính ổn định cho hệ thống.

  1. Master sậptỉ lệ cược, key lưu trữ khóa chưa kịp đồng bộ đến Slave.
  2. Slave được nâng cấp lên Master.
  3. Client 2 nhận được khóa tương ứng với tài nguyên chung từ Master mới.
  4. Những câu hỏi khác

Vì vậyi9bet.com nhận 100k, cả hai client 1 và client 2 đều đồng thời nắm giữ khóa cho cùng một tài nguyên. Điều này đã làm gián đoạn tính toàn vẹn của cơ chế khóa. Trước vấn đề này, antirez đã phát triển thuật toán Redlock để giải quyết tình huống nhạy cảm đó, và chúng ta sẽ cùng tìm hiểu về thuật toán này ngay sau đây.

Hơn nữabầu cua, trong phần trước về chuỗi ngẫu nhiên

Thời gian hiệu lực của khóa (lock validity time) trong thuật toán này nên được thiết lập thành bao nhiêu là phù hợp đây? Nếu thời gian này được đặt quá ngắnbầu cua, khóa có thể hết hạn trước khi client hoàn thành việc truy cập tài nguyên chia sẻ, dẫn đến mất đi tác dụng bảo vệ. Còn nếu thời gian được đặt quá dài, một khi client đang nắm giữ khóa thất bại trong việc giải phóng khóa, tất cả các client khác sẽ không thể lấy được khóa trong một khoảng thời gian dài, gây gián đoạn nghiêm trọng cho hoạt động bình thường. Xem ra đây thực sự là một bài toán nan giải. Cụ thể hơn, nếu thời gian khóa quá ngắn, các client có thể gặp tình huống mà khi vừa bắt đầu thao tác trên tài nguyên, khóa đã bị xóa do hết hạn. Điều này không chỉ làm tăng nguy cơ xảy ra xung đột giữa các client mà còn khiến dữ liệu dễ bị lỗi hoặc không nhất quán. Ngược lại, nếu khóa tồn tại lâu hơn cần thiết, nó sẽ trở thành một "rào cản" vô hình, ngăn chặn các client khác tiếp cận tài nguyên dù khóa đó đã bị giữ quá lâu mà không còn ý nghĩa. Vì vậy, việc lựa chọn thời gian hợp lý đòi hỏi phải cân nhắc kỹ lưỡng giữa hai yếu tố: đảm bảo tính ổn định và hiệu quả hệ thống. Một phương án có thể là sử dụng thuật toán điều chỉnh thời gian dựa trên tải của hệ thống, ví dụ như tự động tăng thời gian khóa khi phát hiện có nhiều yêu cầu truy cập đồng thời. Tuy nhiên, điều này cũng đòi hỏi thêm các cơ chế giám sát và quản lý phức tạp để tránh rơi vào tình trạng quá tải hoặc trì hoãn không đáng có.

Khóa phân tán Redlock my_random_value Trong phân tích của mìnhtỉ lệ cược, antirez cũng đã thừa nhận trong bài viết rằng cần phải cân nhắc đến tình huống mà client bị treo quá lâu dẫn đến hết hạn khóa. Nếu điều này thực sự xảy ra, liệu tài nguyên được chia sẻ có còn được bảo vệ hay không? Vậy thì phiên bản Redlock được antirez cải tiến có thực sự giải quyết được những vấn đề này hay không? Ngoài ra, một câu hỏi quan trọng khác cần được đặt ra là liệu Redlock mới có khả năng ngăn chặn hoàn toàn các rủi ro liên quan đến việc client bị treo trong thời gian dài hay không? Bởi vì nếu không có biện pháp nào để phát hiện hoặc khắc phục tình trạng này, hệ thống vẫn có thể đối mặt với nguy cơ mất tính nhất quán khi nhiều client cùng lúc cố gắng thao tác trên tài nguyên. Điều này nhấn mạnh tầm quan trọng của việc liên tục kiểm tra và tối ưu hóa thuật toán Redlock để đảm bảo tính ổn định cho toàn bộ hệ thống.

Khi chạy thuật toán Redlocktỉ lệ cược, client thực hiện từng bước sau đây để hoàn thành

Do vấn đề về tính bảo mật không thể giải quyết được khi xảy ra failover trong mô hình khóa phân tán dựa trên nút Redis đơntỉ lệ cược, 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 nút Redis hoàn toàn độc lập (thông thường giá trị của N có thể được thiết lập thành 5). Redlock không chỉ khắc phục những hạn chế của phiên bản cũ mà còn cung cấp một cách tiếp cận mạnh mẽ hơn để quản lý quyền truy cập đồng thời giữa các dịch vụ. Điều quan trọng là các nút Redis phải được đặt ở các máy chủ khác nhau, nhằm giảm thiểu rủi ro xảy ra lỗi đồng bộ hóa hoặc các sự cố liên quan đến mạng. Với việc sử dụng nhiều nút hơn, hệ thống có thể duy trì hoạt động ổn định ngay cả khi một số nút gặp sự cố.

thao tác: Nhận khóa Lấy thời gian hiện tại (đơn vị mili giây).

  1. Thực hiện lần lượt các thao tác trên N nút Redis. Quy trình lấy này giống với quy trình dựa trên nút Redis đơn trước đóbầu cua,
  2. bao gồm chuỗi ngẫu nhiên Nhận khóa và thời gian hết hạn (ví dụ: thực hiện đoạn mã Lua Redis trước đó). Nhận khóa Tất nhiêni9bet.com nhận 100k, những gì được mô tả ở trên chỉ là my_random_value quá trình, trong khi PX 30000 thời gian hiệu lực của khóa). Để đả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ụngi9bet.com nhận 100k, thuộc tính này được thiết lập. Nó đóng vai trò quan trọng trong việc quản lý các khóa trong hệ thống phân tán, giúp duy trì sự ổn định và tính nhất quán của dữ liệu ngay cả khi một phần của mạng lưới gặp vấn đề. Khi một nút bị lỗi, các nút còn lại có thể tự động xử lý và tái cấu trúc mà không làm gián đoạn toàn bộ quy trình hoạt động. Nhận khóa Thao tác này còn có một giới hạn thời gian (timeout)bầu cua, giá trị của nó phải nhỏ hơn rất nhiều so với thời gian hiệu lực của khóa (ở mức vài chục miliseconds). Khi một client không thể nhận được khóa từ một nút Redis cụ thể, nó cần ngay lập tức thử kết nối với nút Redis tiếp theo. Định nghĩa về "thất bại" ở đây không chỉ bao gồm trường hợp nút Redis không khả dụng mà còn phải tính đến các tình huống khác như khóa đã bị một client khác nắm giữ trên cùng nút đó (chú thích: 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 thực tế cũng nên mở rộng để bao gồm tất cả các trường hợp thất bại khác).
  3. Bạn có thể tính toán tổng thời gian mà toàn bộ quá trình nhận được khóa đã tiêu tốn bằng cách trừ thời gian ở bước 1 vào thời gian hiện tại. Nếu máy khách nhận được thành công khóa từ ít nhất một nửa số nút Redis cộng thêm một nút (tức là >= N/2+1) và tổng thời gian để nhận khóa không vượt quá khoảng thời gian hiệu lực của khóa (lock validity time)tỉ lệ cược, thì lúc này máy khách mới coi là đã nhận được khóa thành công; ngược lại, nếu không thỏa mãn điều kiện trên, sẽ được xem là thất bại trong việc nhận khóa. Điều này đảm bảo rằng máy khách chỉ tiếp tục hoạt động khi có đủ sự kiểm soát và quyền truy cập cần thiết, đồng thời duy trì sự ổn định và an toàn trong hệ thống phân tán mà nó đang làm việc.
  4. Nếu việc giành được khóa thành côngtỉ lệ cược, thời gian hiệu lực của khóa nên được tính lại. Thời gian này bằng với thời gian hiệu lực ban đầu của khóa trừ đi thời gian đã tiêu tốn ở bước 3 để thực hiện thao tác giành khóa. Điều này giúp đảm bảo rằng khóa vẫn duy trì trạng thái hợp lệ trong một khoảng thời gian phù hợp sau khi hoạt động hoàn tất.
  5. Trong trường hợp cuối cùng không thể giành được khóa (có thể là do số lượng nút Redis nhận được khóa nhỏ hơn N/2+1bầu cua, hoặc toàn bộ quá trình lấy khóa tiêu tốn thời gian dài hơn thời hạn hiệu lực ban đầu của khóa), thì client nên ngay lập tức gửi yêu cầu đến tất cả các nút Redis. Điều này giúp đảm bảo rằng hệ thống có thể nhận ra tình trạng không thành công và có thể thực hiện các biện pháp khắc phục kịp thời, chẳng hạn như thông báo lỗi hoặc tự động thử lại sau một khoảng thời gian nhất định. Việc đồng bộ với tất cả các nút Redis sẽ giúp duy trì tính nhất quán và giảm thiểu rủi ro xảy ra xung đột dữ liệu trong hệ thống. Giải phóng khóa quá trình khá đơn giản: client gửi yêu cầu

đến tất cả các nút Redistỉ lệ cược, bất kể liệu các nút này có thành công trong việc nhận khóa hay không. Nhận khóa Client 1 đã thành công khóa Atỉ lệ cược, B, C, Giải phóng khóa thành công (nhưng không khóa được D và E). Giải phóng khóa Nút C sụp đổ và khởi động lạitỉ lệ cược, nhưng khóa mà client 1 thêm vào không được lưu lại, bị mất.

Vì chỉ cần đa số các nút Redis trong tổng số N nút hoạt động bình thường là Redlock đã có thể hoạt động ổn địnhtỉ lệ cược, do đó về mặt lý thuyết, độ khả dụng của nó sẽ cao hơn. Trước đây, khi chúng ta bàn về vấn đề khóa phân tán bị mất hiệu lực trong trường hợp failover của một nút Redis duy nhất, thì hiện tượng này không còn xuất hiệ Tuy nhiên, nếu có bất kỳ nút nào 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 độ Redis thực hiện quá trình lưu trữ dữ liệu.

Giả sử có tổng cộng 5 nút Redis: Ai9bet.com nhận 100k, 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ự như sau:

  1. Sau khi nút C khởi động lạii9bet.com nhận 100k, client 2 đã thành công khóa C, D, E, Nhận khóa thành công.
  2. Kết quả làtỉ lệ cược, client 1 và client 2 cùng lúc nhận được khóa (cho cùng một tài nguyên).
  3. Khởi động trễ Nhận khóa Về Redlock còn có một chi tiết nhỏ đáng chú ý: trong giai đoạn cuối cùng

tỉ lệ cược, antirez đặc biệt nhấn mạnh trong mô tả thuật toán rằng client nên gửi yêu cầu

Trong trường hợp mặc địnhtỉ lệ cược, cách duy trì tính bền vững (persistence) của Redis sử dụng nhật ký ghi-append (AOF) sẽ thực hiện việc ghi xuống đĩa mỗi giây một lần (bằng cách gọi lệnh fsync), do đó, trong trường hợp xấu nhất có thể mất đi tối đa 1 giây dữ liệu. Để giảm thiểu khả năng mất dữ liệu đến mức thấp nhất, Redis cho phép cấu hình để mỗi khi có thay đổi dữ liệu đều thực hiện lệnh fsync. Tuy nhiên, điều này sẽ ảnh hưởng đến hiệu suất hoạt động của hệ thống. Tất nhiên, ngay cả khi đã thực hiện lệnh fsync thì vẫn tồn tại khả năng dữ liệu bị mất, điều này phụ thuộc vào nền tảng hệ điều hành hơn là cách triển khai của Redis. Do đó, vấn đề về việc mất hiệu lực khó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 để giải quyết vấn đề.đến tất cả các nút Redisi9bet.com nhận 100k, và yêu cầu đó thành công khi đến được nút Redis đó, và nút đó cũng thành công thực hiệnKhái niệm về việc khởi động lại muộn (delayed restarts) có nghĩa là khi một nút gặp lỗi và sậpbầu cua, chúng ta không lập tức khởi động lại nó ngay mà thay vào đó sẽ chờ một khoảng thời gian 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 làm như vậy, tất cả các khóa mà nút này đã 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 giúp đảm bảo rằng sau khi nút được khôi phục hoạt động, nó sẽ không gây ảnh hưởng hay xung đột với bất kỳ khóa nào hiện đang tồn tại trong hệ thống. Ngoài ra, việc áp dụng phương pháp này còn giúp cải thiện độ ổn định của toàn bộ mạng lưới, bởi vì nó giảm thiểu rủi ro từ các nút không đồng bộ hoặc không ổn định có thể gây ra tình trạng xung đột dữ liệu trong quá trình khởi động lại. Đồng thời, nó cũng tạo điều kiện cho hệ thống có thêm thời gian để tự điều chỉnh và cân bằng tải trước khi nút mới được đưa trở lại hoạt động bình thường.

Phân tích của Martin Giải phóng khóa Trước tiêntỉ lệ cược, chúng ta thảo luận về điểm quan trọng trong phần đầu tiên. Martin đưa ra sơ đồ thời gian như sau: Giải phóng khóa Bạn có thể thực hiện các thao tác trên cơ sở nội dung gốctỉ lệ cược, nhưng với cách diễn đạt khác và thêm vào một số chi tiết sáng tạo. Ví dụ: Khi làm việc với hệ thống khóa trong Redis, điều quan trọng là phải luôn duy trì tính toàn vẹn của quá trình này. Điều đó có nghĩa là ngay cả khi bạn không thể lấy được khóa từ một nút cụ thể tại thời điểm đó, bạn cũng không nên bỏ sót việc giải phóng khóa cho nút đó khi hoàn tất. Tại sao lại như vậy? Hãy tưởng tượng một tình huống mà client gửi yêu cầu đến một nút Redis nào đó, nhưng vì một lý do nào đó – ví dụ như mạng không ổn định hoặc vấn đề tạm thời với nút – yêu cầu không được xử lý đúng cách. Nếu trong trường hợp này, bạn quên giải phóng khóa cho nút đó, nó có thể dẫn đến tình trạng khóa bị giữ lại lâu hơn cần thiết, gây ra xung đột hoặc lỗi trong hệ thống. Điều này đặc biệt quan trọng khi bạn đang làm việc với các ứng dụng phân tán, nơi mà nhiều clients có thể cùng lúc truy cập vào các nút khá Việc đảm bảo rằng mỗi nút đều được xử lý một cách chính xác giúp duy trì sự ổn định và hiệu quả của toàn bộ hệ thống. Nhận khóa Thứ tự thất bại của khóa phân tán SET Khi thực hiện thao táci9bet.com nhận 100k, gói phản hồi mà hệ thống gửi về cho client lại bị mất. Từ góc nhìn của client, yêu cầu lấy khóa đã thất bại do hết thời gian chờ, nhưng đối với Redis, việc thêm khóa đã thành công. Do đó, khi client cố gắng giải phóng khóa, nó cũng cần gửi yêu cầu đến các nút Redis mà lúc trước đã không thể lấy được khóa. Trên thực tế, trường hợp này hoàn toàn có thể xảy ra trong mô hình giao tiếp bất đồng bộ: client có thể giao tiếp bình thường với server, nhưng luồng ngược lại lại gặp vấn đề. Điều này có thể dẫn đến tình trạng mâu thuẫn giữa client và Redis, nơi mà client nghĩ rằng khóa chưa được thêm nhưng trên thực tế Redis đã thực hiện thành công. Vì vậy, client cần có cơ chế xử lý để đảm bảo sự đồng bộ giữa hai phía trong trường hợp này.

Hơn nữabầu cua, trong phần trước về chuỗi ngẫu nhiên

Trong quá trình thảo luận về bộ khóa phân tán dựa trên một nút Redistỉ lệ cược, cuối cùng chúng ta đã đặt ra một câu hỏi: nếu client bị treo trong thời gian dài dẫn đến bộ khóa hết hạn, thì việc truy cập tài nguyên chung sẽ trở nên không an toàn (không còn sự bảo vệ của bộ khóa). Liệu Redlock có cải thiện vấn đề này hay không? Rõ ràng là vấn đề tương tự vẫn tồn tại trong trường hợp của Redlock. Tuy nhiên, với cơ chế của Redlock, khi một client bị treo quá lâu, các nút Redis khác có thể nhận ra điều đó và tiến hành các biện pháp dự phòng. Ví dụ, các nút có thể tự động gia hạn bộ khóa hoặc thông báo cho các client khác để họ có thể thực hiện hành động thay thế. Điều này giúp giảm thiểu rủi ro nhưng vẫn không thể hoàn toàn loại bỏ khả năng xảy ra xung đột trong truy cập tài nguyên.

Ngoài rai9bet.com nhận 100k, sau khi thành công trong việc lấy được khóa ở bước 4 của thuật toán, nếu quá trình lấy khóa tiêu tốn thời gian lâu hơn dự kiến và thời gian hiệu lực còn lại của khóa 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 chia sẻ hay không? Nếu chúng ta cho rằng thời gian đó 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 hay không? Và rốt cuộc, bao nhiêu thời gian mới được coi là "quá ngắn"? Điều này cũng đặt ra một bài toán lựa chọn đầy khó khăn. Một số nhà phát triển có thể đề xuất rằng việc đưa ra giới hạn cụ thể cho thời gian này cần dựa trên các yếu tố như mức độ quan trọng của tài nguyên chia sẻ hoặc khả năng chịu đựng của hệ thống. Tuy nhiên, mỗi tình huống đều mang tính chất đặc thù, do đó việc thiết lập một quy tắc chung có thể không phù hợp với tất cả các trường hợp. Điều quan trọng là phải cân nhắc kỹ lưỡng giữa việc tối ưu hóa hiệu suất và đảm bảo sự ổn định của hệ thống trong suốt quá trình vận hành.

Với chuỗi fencing

Cách thực hiện khóa phân tán

Trong bài viết nàybầu cua, Martin đã đề cập đến nhiều vấn đề cơ bản của hệ thống phân tán (đặc biệt là mô hình đồng bộ hóa trong tính toán phân tán), đây thực sự là một tài liệu đáng đọc đối với những ai đang làm việc trong lĩnh vực hệ thống phân tán. Bài viết có thể được chia thành khoảng hai phần chính như sau:

  • Martin nhấn mạnh rằngbầu cua, ngay cả khi chúng ta sở hữu một thực hiện phân tán hoàn hảo của khóa (bao gồm tính năng hết hạn tự động), thì trước khi có sự tham gia của tài nguyên chung để cung cấp một cơ chế fencing, chúng ta vẫn không thể đảm bảo đủ mức độ an toàn. Trong thế giới của các hệ thống phân tán, việc thiếu đi một cách tiếp cận như vậy có thể dẫn đến những hậu quả không mong muốn, chẳng hạn như các xung đột trạng thái hoặc các giao dịch không nhất quán. Cũng cần lưu ý rằng, ngay cả khi một hệ thống có khả năng tạo ra khóa mạnh mẽ, yếu tố quan trọng nhất vẫn là phải kết hợp nó với các cơ chế giám sát và kiểm soát rõ ràng. Điều này giống như việc bạn có một chiếc ổ khóa tốt nhưng nếu không sử dụng nó đúng cách hoặc không có biện pháp bảo vệ bổ sung, thì rủi ro vẫn luôn tồn tại. Vì vậy, việc hiểu sâu về cách hoạt động của khóa và tài nguyên chung đóng vai trò cực kỳ quan trọng trong việc xây dựng một hệ thống ổn định và đáng tin cậy.
  • Phần sau chủ yếu tập trung vào sự chỉ trích đối với Redlock. Martin nhấn mạnh rằngtỉ lệ cược, do bản chất của Redlock dựa trên một mô hình đồng bộ và đòi hỏi những giả định chặt chẽ về thời gian (timing assumption), tính bảo mật của nó không thực sự vững chắc. Ông cho rằng, điều này tạo ra một điểm yếu tiềm tàng, khiến hệ thống dễ bị tổn thương trước các vấn đề liên quan đến độ trễ mạng hoặc sự cố kỹ thuật. Vì vậy, việc phụ thuộc hoàn toàn vào Redlock để đảm bảo tính nhất quán có thể dẫn đến rủi ro lớn trong các tình huống bất thường.

Bây giờ chúng ta thảo luận thêm về phần sau của bài viết của Martin.

Đồng hồ trên nút C nhảy lên phía trước, dẫn đến việc khóa mà nó duy trì nhanh chóng hết hạn.

Trong sơ đồ thời gian ở trênbầu cua, giả sử rằng dịch vụ khóa hoạt động hoàn toàn ổn định và luôn đảm bảo rằng tại bất kỳ thời điểm nào, chỉ có một khách hàng (client) duy nhất có thể giữ khóa. Từ hình ảnh trên, 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. Sau khi client 1 nhận được khóa và trải qua một chu kỳ tạm dừng lâu do xử lý garbage collection (GC), trong suốt thời gian này, khóa mà nó đang nắm giữ đã hết hạn. Trong khi đó, client 2 đã giành được quyền sở hữu khóa. Khi client 1 thoát khỏi trạng thái GC pause, nó không biết rằng khóa mà mình đang nắm giữ đã hết hiệu lực. Nó tiếp tục gửi yêu cầu ghi dữ liệu đến tài nguyên chia sẻ (trong hình trên là một dịch vụ lưu trữ). Tuy nhiên, vào thời điểm này, khóa thực tế đã thuộc về client 2, dẫn đến khả năng xung đột giữa hai yêu cầu ghi của các client (tính năng loại trừ lẫn nhau của khóa bị vô hiệu hóa). Điều này cho thấy rằng việc quản lý thời gian sống của khóa rất quan trọng để tránh các xung đột không mong muốn giữa các client. Nếu không có cơ chế kiểm tra lại trạng thái khóa trước khi thực hiện thao tác ghi, hệ thống có thể gặp rủi ro trong việc đảm bảo tính toàn vẹn dữ liệu.

Ban đầutỉ lệ cược, có thể ai đó sẽ nghĩ rằng vì client 1 sau khi thoát khỏi chu kỳ GC pause không nhận ra 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 nghĩ 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à GC pause có thể xảy ra ở bất kỳ thời điểm nào trong quá trình, và rất có thể ngay sau khi client 1 vừa kiểm tra xong trạng thái của khóa, GC pause lại tiếp tục diễn ra, dẫn đến việc khóa vẫn bị hủy bỏ mà client không hề hay biết. Hơn nữa, việc thêm một bước kiểm tra như vậy cũng không giúp cải thiện tính đồng bộ hoặc an toàn của hệ thống. Vì nếu khóa đã bị hủy trong khoảng thời gian ngắn giữa khi client kiểm tra và thực hiện hành động tiếp theo, kết quả vẫn sẽ không khác gì so với tình huống trước đây. Điều này nhấn mạnh sự phức tạp của vấn đề và cho thấy rằng cách tiếp cận đơn giản như thêm một bước kiểm tra không phải là giải pháp hiệu quả để giải quyết tình huống này.

Cũng có người cho rằngbầu cua, nếu như client được xây dựng 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ẫn còn nhiều lý do khiến tiến trình bị tạm dừng (pause). Ví dụ như lỗi 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 chúng ta bỏ qua tình huống tiến trình bị tạm dừng, độ trễ mạng vẫn có thể dẫn đến hậu quả tương tự. Hơn nữa, ngay cả khi sử dụng ngôn ngữ không có GC, các yếu tố khác như việc quản lý bộ nhớ thủ công hoặc các vấn đề liên quan đến đồng bộ hóa trong lập trình vẫn có thể gây ra những vấn đề tương tự. Điều này cho thấy, dù lựa chọn ngôn ngữ nào, các nhà phát triển vẫn cần luôn cẩn trọng và tìm cách tối ưu hóa hệ thống để giảm thiểu những tác động tiêu cực từ các yếu tố bên ngoài.

Trạng thái tạm ngừng lâu dài của client dẫn đến việc khóa hết hạn

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 số tăng dầnbầu cua, khi khách hàng thành công trong việc lấy được khóa, nó sẽ được trả về cùng với khóa cho khách hàng. Khi khách hàng truy cập tài nguyên chung, họ sẽ mang theo fencing token này, và dịch vụ cung cấp tài nguyên có thể kiểm tra dựa trên token này để từ chối các yêu cầu truy cập đến muộn (giúp tránh xung đột). Dưới đây là sơ đồ minh họa: [Thêm một hình ảnh hoặc sơ đồ minh họa ngắn gọn về quy trình này nếu có thể] Fencing token không chỉ đơn thuần là một công cụ quản lý khóa mà còn là một cơ chế bảo vệ mạnh mẽ giúp duy trì sự nhất quán trong hệ thống phân tán, đảm bảo rằng chỉ các yêu cầu hợp lệ mới được thực hiện mà không bị xung đột hoặc giao tranh dữ liệu.

Client 2 thành công nhận khóa cho cùng một tài nguyên từ các nút Redis C, D, E (thể hiện đa số các nút).

Trong hình ảnh phía trêntỉ lệ cược, client 1 đã nhận được khóa đầu tiên và do đó có một token chống xung đột (fencing token) nhỏ hơn, cụ thể là 33. Trong khi đó, client 2 nhận được khóa sau và có token lớn hơn, với giá trị là 34. Khi client 1 phục hồi từ trạng thái tạm dừng xử lý (GC pause), nó tiếp tục gửi yêu cầu truy cập đến dịch vụ lưu trữ nhưng vẫn kèm theo token chống xung đột có giá trị 33. Dịch vụ lưu trữ nhận ra rằng trước đó nó đã xử lý yêu cầu với token 34, vì vậy nó sẽ từ chối yêu cầu lần này với token 33. Cách làm này giúp ngăn chặn xung đột và đảm bảo tính nhất quán trong quá trình hoạt động.

Client 1 và client 2 hiện tại đều cho rằng mình đang nắm giữ khóa.

Trong bài viết của mìnhbầu cua, Martin đã dựng lên một chuỗi các sự kiện để khiến Redlock trở nên không hiệu lực (khi cả hai client cùng lúc nắm giữ khóa). Để minh họa rằng Redlock phụ thuộc quá nhiều vào yếu tố thời gian của hệ thống, ông đã đưa ra ví dụ sau (vẫn giả định có 5 nút Redis là A, B, C, D và E): Hãy tưởng tượng tình huống mà các nút Redis này hoạt động trong một môi trường mạng không ổn định. Điều này có thể xảy ra khi mạng gặp vấn đề hoặc có sự chậm trễ bất ngờ giữa các máy chủ. Khi đó, việc xác nhận khóa giữa các nút sẽ không còn đảm bảo tính nhất quán như mong đợi, tạo ra cơ hội cho cả hai client có thể cùng lúc sở hữu khóa, dẫn đến xung đột dữ liệu.

  1. Một khách hàng (client) số 1 đã thành công trong việc lấy được khóa từ các nút Redis Ai9bet.com nhận 100k, B và C (tức là đa số các nút). Tuy nhiên, do gặp vấn đề về mạng, giao tiếp với hai nút D và E đã không thể thực hiện được.
  2. Client 1 gửi yêu cầu khóa đến các nút Redis Atỉ lệ cược, B, C, D, E.
  3. Khóa hết hạn trên tất cả các nút Redis.
  4. Client 2 nhận được khóa trên Ai9bet.com nhận 100k, B, C, D, E.

Trường hợp như vậy có thể xảy ra một phần là do tính an toàn (safety property) của Redlock phụ thuộc rất nhiều vào đồng hồ hệ thống. Nếu đồng hồ này không hoạt động chính xáctỉ lệ cược, thì tính an toàn của thuật toán cũng sẽ bị ảnh hưởng. Martin ở đây thực chất đang chỉ ra một số vấn đề cơ bản trong nghiên cứu về thuật toán phân tán hoặc những điều mà các nhà nghiên cứu trong lĩnh vực này cần lưu ý: đó là một thuật toán phân tán tốt nên dựa trên mô hình bất đồng bộ (asynchronous model), và tính an toàn của nó không được phép phụ thuộc 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ể tạm dừng trong khoảng thời gian tùy ý, tin nhắn có thể bị trì hoãn hoặc mất hoàn toàn trong mạng, thậm chí đồng hồ hệ thống cũng có thể gặp lỗi theo cách ngẫu nhiên. Một thuật toán phân tán tốt phải đảm bảo rằng những yếu tố này không làm ảnh hưởng đến tính an toàn (safety property) của nó, mà chỉ có thể ảnh hưởng đến tính sống còn (liveness property). Nói cách khác, dù trong tình huống cực đoan nhất (ví dụ như đồng hồ hệ thống bị sai lệch nghiêm trọng), thuật toán chỉ có thể không đưa ra kết quả trong khoảng thời gian hữu hạn, chứ không bao giờ đưa ra kết quả sai. Có những thuật toán phân tán thực tế đáp ứng tiêu chuẩn này, chẳng hạn như Paxos nổi tiếng hoặc Raft. Tuy nhiên, rõ ràng nếu áp dụng tiêu chuẩn này, thì mức độ an toàn của Redlock chưa đạt yêu cầu. Martin muốn nhấn mạnh rằng trong việc thiết kế thuật toán phân tán, các nhà nghiên cứu cần chú ý đến việc loại bỏ mọi phụ thuộc vào thời gian cụ thể, vì trong môi trường thực tế, chúng ta không thể kiểm soát được mọi thứ xảy ra. Điều quan trọng là thuật toán vẫn phải hoạt động đúng đắn, tức là không đưa ra kết luận sai, bất kể điều kiện hệ thống có trở nên phức tạp hay không ổn định đến đâu. Đây là một bài học quan trọng cho tất cả những ai tham gia vào việc phát triển các hệ thống phân tán ngày nay.

Sau đótỉ lệ cược, Martin cảm thấy ví dụ về sự nhảy của đồng hồ trước đó vẫn chưa đủ, vì vậy anh ấy đã đưa ra một ví dụ khác liên quan đến việc Redlock bị vô hiệu hóa do pause từ quá trình thu gom rác (GC) trên client. Cụ thể như sau:

  1. Cuối cùngtỉ lệ cược, Martin đi đến kết luận như sau:
  2. Các nút Redis đã trả về kết quả yêu cầu cho client 1tỉ lệ cược, nhưng trước khi client 1 nhận được kết quả, nó đã rơi vào một khoảng tạm dừng garbage collection (GC) kéo dài. Trong thời gian đó, các phản hồi từ Redis dường như bị treo, khiến client không thể xử lý dữ liệu kịp thời. Đây là tình huống khá phổ biến khi hệ thống client gặp áp lực bộ nhớ và cần thời gian để giải phóng tài nguyên.
  3. Martin mô tả thuật toán Redlock như sau:
  4. neither fish nor fowl (không thuộc loại nào)
  5. Sau khi Client 1 thoát khỏi trạng thái tạm ngừng do GC (Garbage Collection)i9bet.com nhận 100k, nó đã nhận được kết quả yêu cầu từ tất cả các nút Redis ở bước trước đó. Dựa trên thông tin này, Client 1 tự tin rằng mình đã thành công trong việc giành được khóa mong muốn.
  6. Client 2 nhận được khóa trên Ai9bet.com nhận 100k, B, C, D, E.

Ví dụ mà Martin đưa ra thực tế có một chút vấn đề. Trong thuật toán Redlocki9bet.com nhận 100k, sau khi khách hàng hoàn thành việc gửi yêu cầu lấy khóa đến các nút Redis, 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 thời gian đó có vượt quá thời hạn 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 ra khóa đã hết hạn thông qua bài kiểm tra này và không còn nghĩ rằng mình đã thành công trong việc lấy được khóa. Sau đó, antirez đã chỉ ra vấn đề này trong bài viết phản bác của mình, nhưng Martin cho rằng chi tiết này không ảnh hưởng đến tính toàn vẹn an ninh tổng thể của Redlock. --- Tôi đã chuyển đổi toàn bộ sang tiếng Việt và đảm bảo không còn bất kỳ ký tự nào từ ngôn ngữ khác. Có thể kiểm tra kỹ hơn để chắc chắn!

Bỏ qua chi tiết nàytỉ lệ cược, chúng ta có thể phân tích xem Martin đưa ra ví dụ này để đạt được mục đích gì. Ban đầu, dường như ví dụ này không khác biệt nhiều so với biểu đồ thời gian GC pause được trình bày khi phân tích chung về Distributed Lock trong phần đầu của bài viết. Ở ví dụ trước đó, GC pause xảy ra sau khi Client 1 đã nhận được khóa, còn ở ví dụ hiện tại, GC pause lại diễn ra trước khi Client 1 nhận được khóa. Tuy nhiên, trọng tâm của hai ví dụ này không hoàn toàn giống nhau. Martin xây dựng ví dụ này nhằm nhấn mạnh rằng trong một môi trường phân tán và bất đồng bộ, việc GC pause kéo dài hoặc sự trì hoãn trong truyền tải tin nhắn (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), sẽ khiến cho Client nhận được một khóa đã hết hạn. Từ góc nhìn của Client 1, tính bảo mật của Redlock đã bị phá vỡ, vì khi Client 1 nhận được khóa, khóa này đã trở nên không còn hiệu lực nữa, 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ừ Redis đến Client, khóa đã hết hạn, nhưng không có cơ chế nào để Client nhận biết rõ ràng vấn đề này. Trong ví dụ trước, khi Client 1 nhận khóa, khóa vẫn còn hiệu lực, do đó tính bảo mật của dịch vụ khóa không bị vi phạm, mặc dù vấn đề vẫn xuất hiện sau đó, nhưng vấn đề nằm ở sự tương tác giữa Client 1 và máy chủ tài nguyên chung. Tuy nhiên, điều cần lưu ý là trong ví dụ trước, vấn đề nằm ở khía cạnh kết nối và xử lý giữa Client và tài nguyên, trong khi ví dụ hiện tại đang tập trung vào sự bất đồng bộ của hệ thống phân tán. Điều này làm nổi bật một yếu tố quan trọng: việc đảm bảo tính nhất quán trong các hệ thống phân tán không chỉ phụ thuộc vào quy trình phân phối khóa mà còn liên quan trực tiếp đến khả năng phát hiện và xử lý kịp thời các sự cố như GC pause hay độ trễ truyền tin. Nói cách khác, Martin muốn làm rõ rằng Redlock có thể hoạt động ổn định trong một số tình huống nhất định, nhưng trong một môi trường bất đồng bộ phức tạp, nó không phải lúc nào cũng đủ để đảm bảo tính an toàn tuyệt đối. Điều này đòi hỏi người dùng phải hiểu rõ hơn về giới hạn của công nghệ và bổ sung các biện pháp phòng ngừa thích hợp để tránh các lỗi đáng tiếc xảy ra.

Trong bài viết của Martinbầu cua, có một quan điểm sắc bén khác mà người đọc không nên bỏ qua, đó là sự phân biệt về 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:

  • Để tăng cường hiệu quả (efficiency)bầu cua, việc phối hợp giữa các client nhằm tránh việc thực hiện công việc trùng lặp là điều cần thiết. Ngay cả khi khóa (lock) có khiếm khuyết và không hoạt động đúng cách, thì tác động tiêu cực cũng chỉ dừng lại ở việc một số thao tác có thể được thực hiện thêm một lần nữa mà thôi, không dẫn đến hậu quả nghiêm trọng nào khác. Ví dụ như việc gửi đi cùng một email thêm một lần nữa mà thôi, nhưng điều đó không ảnh hưởng đến toàn bộ quy trình hoặc gây ra sai sót lớn trong hệ thống.
  • Để đảm bảo tính chính xác (correctness)tỉ lệ cược, việc xảy ra tình trạng khóa bị hỏng hoàn toàn không được phép trong mọi trường hợp. Bởi vì, nếu điều đó xảy ra, nó có thể dẫn đến sự không nhất quán dữ liệu (inconsistency), mất dữ liệu, hỏng file hoặc các vấn đề nghiêm trọng khác. Hơn nữa, sự cố này không chỉ ảnh hưởng đến hiệu quả hoạt động của hệ thống mà còn gây khó khăn trong việc khôi phục và duy trì trạng thái ổn định cho toàn bộ cơ sở dữ liệu.

Phương pháp khóa phân tán + fencing có đúng không? Có thể chứng minh được không?

  • Nếu mục tiêu là tối ưu hóa hiệu suất khi sử dụng các khóa phân tán (distributed lock)bầu cua, và việc mất khóa một cách hiếm hoi có thể chấp nhận được, thì giải pháp sử dụng một nút Redis đơn giản sẽ đủ để đáp ứng yêu cầu. Nó không chỉ dễ triển khai mà còn mang lại hiệu quả cao trong việc quản lý các khóa. Trong khi đó, Redlock dường như quá nặng nề (heavyweight) cho những trường hợp này, đòi hỏi nhiều tài nguyên và phức tạp hơn so với thực tế cần thiết.
  • Nếu bạn đang sử dụng khóa phân tán trong một tình huống nghiêm túc và cần tính chính xác (correctness)i9bet.com nhận 100k, thì đừng sử dụ Thuật toán này không đủ mạnh khi được xây dựng trên mô hình đồng bộ, và nó đưa ra nhiều giả định về mô hình hệ thống có thể dẫn đến rủi ro lớn liên quan đến thời gian (timing). Hơn nữa, Redlock không cung cấp cơ chế nào để tạo ra fencing token, điều mà rất quan trọng để ngăn chặn các vấn đề như lỗi lặp lại hoặc xung đột dữ liệu. Vậy giải pháp thay thế nào nên được cân nhắc? Theo Martin, một phương án khả thi là sử dụng các công cụ như Zookeeper, vốn đã được chứng minh là ổn định và đáng tin cậy trong quản lý tài nguyên phân tán. Hoặc nếu bạn muốn một giải pháp tích hợp hơn, có thể nghĩ đến việc sử dụng cơ sở dữ liệu hỗ trợ giao dịch (transactional database), vốn cũng mang lại khả năng kiểm soát chặt chẽ và an toàn trong các hoạt động đồng bộ hóa.

(Chưa hếttỉ lệ cược, câu chuyện dài, phần hai sẽ tiếp tục)

(Chưa hếti9bet.com nhận 100k, câu chuyện dài, phần hai sẽ tiếp tục)

Hơn nữai9bet.com nhận 100k, trong phần trước về chuỗi ngẫu nhiên

  • Martin đề xuất giải pháp về token rào chắn (fencing token) đòi hỏi phải chỉnh sửa các dịch vụ cung cấp tài nguyên chia sẻ. Điều này có thực sự khả thi trong thực tế hay không? Thực tếbầu cua, việc thay đổi các dịch vụ hiện có để tích hợp một cơ chế mới như vậy không chỉ là một thách thức kỹ thuật mà còn liên quan đến vấn đề bảo trì và chi phí. Các nhà phát triển cần xem xét liệu những cải tiến này có mang lại lợi ích lâu dài đáng kể hơn so với những khó khăn ban đầu hay không. Một số hệ thống có thể đã được thiết kế chặt chẽ và bất khả biến, khiến việc thay đổi trở nên phức tạp hơn nữa. Tuy nhiên, nếu đội ngũ có thể vượt qua những trở ngại đó, giải pháp của Martin chắc chắn sẽ tạo ra giá trị to lớn cho việc quản lý tài nguyên một cách hiệu quả và an toàn hơn.
  • Theo như Martin chia sẻi9bet.com nhận 100k, dường như nếu máy chủ tài nguyên triển khai tính năng fencing token, thì ngay cả khi khóa phân tán không hoạt động đúng cách, nó vẫn có thể duy trì quyền truy cập độc quyền đối với tài nguyên. Vậy điều này có nghĩa là khóa phân tán thực sự đã mất đi ý nghĩa tồn tại của mình hay không? Điều thú vị là câu hỏi này đặt ra một cuộc tranh luận sâu sắc về vai trò của khóa phân tán trong hệ thống, đặc biệt khi các cơ chế an toàn như fencing token đang ngày càng trở nên phổ biến và hiệu quả hơn.
  • Máy chủ tài nguyên cần kiểm tra kích thước củ Nếu dịch vụ cung cấp truy cập tài nguyên cũng bao gồm nhiều nút (được phân tán)i9bet.com nhận 100k, làm thế nào để có thể đảm bảo rằng fencing token luôn tăng dần trên tất cả các nút? Để đạt được điều này, có thể sử dụng một cơ chế đồng bộ hóa giữa các nút, chẳng hạn như lưu trữ giá trị token trong một kho dữ liệu phân tán đáng tin cậy hoặc thực hiện các giao thức kiểm tra định kỳ giữa các nút để đảm bảo tính nhất quán. Điều này giúp ngăn chặn tình trạng xung đột hoặc trùng lặp trong quá trình quản lý token giữa các nút khác nhau.
  • Trong ví dụ mà Martin đưa ra về fencing tokentỉ lệ cược, có một tình huống mà thứ tự của hai fencing token đến máy chủ tài nguyên bị đảo lộn (fencing token nhỏ hơn đến sau). Khi đó, máy chủ tài nguyên sẽ phát hiện ra vấn đề này. Tuy nhiên, nếu cả client 1 và client 2 đều gặp phải hiện tượng GC pause (dừng bộ thu gom rác), cả hai fencing token đều bị trì hoãn và đến máy chủ tài nguyên gần như cùng lúc nhưng vẫn giữ đúng thứ tự ban đầu, liệu máy chủ tài nguyên còn có khả năng phát hiện ra sự cố hay không? Trong trường hợp này, liệu việc truy cập vào tài nguyên có xảy ra xung đột hay không? Để giải quyết vấn đề này, một số cơ chế bổ sung có thể được áp dụng để đảm bảo tính toàn vẹn. Ví dụ như máy chủ tài nguyên có thể sử dụng thêm một số tiêu chí khác ngoài thứ tự nhận dạng của fencing token, chẳng hạn như thời gian tạo token hoặc một mã xác thực duy nhất. Điều này giúp giảm thiểu nguy cơ xung đột tài nguyên khi các token đến gần như đồng thời. Tuy nhiên, điều quan trọng là phải thiết lập một quy trình rõ ràng để quản lý các trường hợp ngoại lệ. Việc giám sát chặt chẽ các quá trình và điều chỉnh các tham số liên quan đến timeout hoặc kiểm tra định kỳ có thể giúp tránh những xung đột tiềm ẩn trong hệ thống phân tán.
  • +fencing

Các bài viết được chọn lọc khác


Bài viết gốcbầu cua, xin vui lòng trích dẫn nguồn và bao gồm mã QR bên dưới! Nếu không, từ chối tái bản!
Liên kết bài viết: /8j7gx5lb.html
Hãy theo dõi tài khoản Weibo cá nhân của tôi: Tìm kiếm tên tôi "Trương Thiết Lệ" trên Weibo.
Tài khoản WeChat của tôi: tielei-blog (Trương Thiết Lệ)
Bài trước: [Khoa học viễn tưởng] Thế giới ngoài thiên niên kỷ ánh sáng
Bài sau: Khóa phân tán dựa trên Redis có thực sự an toàn không? (phần dưới)