Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Dynamo: Amazon’s Highly Available Key-value Store

269 views

Published on

Đảm bảo tính tin cậy trong hệ thống lớn là một trong những thách thức lớn nhất phải đối mặt tại Amazon, một trong những nền tảng thương mại điện tử lớn nhất trên thế giới. Một gián đoạn trên nền tảng Amazon có thể gây ra những hậu quả tài chính to lớn và ảnh hưởng đến sự tin tưởng của khách hàng. Nền tảng Amazon, cung cấp dịch vụ cho nhiều trang web trên toàn thế giới, được hoạt động dựa trên một cơ sở hạ tầng của mười ngàn server và các thành phần network đặt ở nhiều trung tâm dữ liệu trên toàn thế giới. Với quy mô này, các thành phần nhỏ và lớn có thể tiếp tục bị lỗi và việc xây dựng hệ thống quảnlýcóthểđốimặtvớicáclỗinàysẽmanglạitính tin cậy và tính mở rộng của các hệ thống phần mềm. Bài báo này sẽ giới thiệu về mô hình thiết kế và cách thức hoạt động của hệ thống Dynamo - một hệ thống lưu trữ dạng key-value có tính sẵn sàng cao, một vài dịch vụ cốt lỗi của Amazon sử dụng nó để cung cấp trải nghiệm “always-on”. Để đạt được mức độ sẵn sàng này, Dynamo hy sinh tính nhất quán dưới các ngữ cảnh xảy ra lỗi nhất định.

Published in: Data & Analytics
  • Be the first to comment

  • Be the first to like this

Dynamo: Amazon’s Highly Available Key-value Store

  1. 1. Dynamo: Amazon’s Highly Available Key-value Store Giuseppe DeCandia, Deniz Hastorun, Madan Jampani, Gunavardhan Kakulapati, Avinash Lakshman, Alex Pilchin, Swaminathan Sivasubramanian, Peter Vosshall and Werner Vogels Amazon.com ABSTRACT Đảm bảo tính tin cậy trong hệ thống lớn là một trong những thách thức lớn nhất phải đối mặt tại Amazon, một trong những nền tảng thương mại điện tử lớn nhất trên thế giới. Một gián đoạn trên nền tảng Amazon có thể gây ra những hậu quả tài chính to lớn và ảnh hưởng đến sự tin tưởng của khách hàng. Nền tảng Amazon, cung cấp dịch vụ cho nhiều trang web trên toàn thế giới, được hoạt động dựa trên một cơ sở hạ tầng của mười ngàn server và các thành phần network đặt ở nhiều trung tâm dữ liệu trên toàn thế giới. Với quy mô này, các thành phần nhỏ và lớn có thể tiếp tục bị lỗi và việc xây dựng hệ thống quản lý có thể đối mặt với các lỗi này sẽ mang lại tính tin cậy và tính mở rộng của các hệ thống phần mềm. Bài báo này sẽ giới thiệu về mô hình thiết kế và cách thức hoạt động của hệ thống Dynamo - một hệ thống lưu trữ dạng key-value có tính sẵn sàng cao, một vài dịch vụ cốt lỗi của Amazon sử dụng nó để cung cấp trải nghiệm “always-on”. Để đạt được mức độ sẵn sàng này, Dynamo hy sinh tính nhất quán dưới các ngữ cảnh xảy ra lỗi nhất định. 1 INTRODUCTION Amazon cung cấp một nền tảng thương mại điện tử phục vụ cho hàng triệu khách hàng trên thế giới. Tại giờ cao điểm, Amazon có thể sử dụng hàng triệu máy chủ nằm rải rác trên thế giới để phục vụ người dùng. Do đó có nhiều yêu cầu chặt chẽ đặt ra cho nền tảng của Amazon như hiệu năng, độ tin cậy, tính hiệu quả và để hỗ trợ sự tăng trưởng liên tục, nền tảng cần phải có khả năng mở rộng cao. Trong đó tính tin cậy là một trong những yêu cầu quan trọng nhất bởi sự gián đoạn của hệ thống có thể gây ra những hậu quả tài chính to lớn và làm ảnh hưởng đến sự tin tưởng của khách hàng khi sử dụng nền tảng của Amazon. Ngoài ra, để hỗ trợ tăng trưởng liên tục, nền tảng cần phải có khả năng mở rộng rất cao. Một trong những bài học được học hỏi từ việc vận hành nền tảng của Amazon là độ tin cậy và khả năng mở rộng của một hệ thống phụ thuộc vào cách quản lý trạng thái ứng dụng của nó. Amazon sử dụng một kiến trúc định hướng dịch vụ được phân cấp, bao gồm hàng trăm dịch vụ. Trong môi trường này có một nhu cầu đặc biệt về công nghệ lưu trữ luôn sẵn có. Ví dụ: khách hàng có thể xem và thêm các mặt hàng vào giỏ hàng của họ ngay cả khi ổ đĩa bị hỏng, đường truyền mạng bị trục trặc, hoặc các trung tâm dữ liệu đang bị phá hủy. Do đó, dịch vụ chịu trách nhiệm quản lý giỏ hàng đòi hỏi phải luôn ghi và đọc dữ liệu từ kho dữ liệu của nó và dữ liệu của nó cần phải có sẵn trên nhiều trung tâm dữ liệu. Xử lý các lỗi trong cơ sở hạ tầng bao gồm hàng triệu thành phần là phương thức hoạt động chuẩn của chúng tôi; Luôn có một số lượng nhỏ các máy chủ và các thành phần mạng bị hỏng tại bất kỳ thời điểm nào. Vì vậy các hệ thống phần mềm của Amazon cần phải được xây dựng theo cách xử lý sự cố như là một trường hợp bình thường mà không ảnh hưởng đến tính sẵn sàng hoặc hiệu năng. Để đáp ứng nhu cầu về độ tin cậy và khả năng mở rộng, Amazon đã phát triển một số công nghệ lưu trữ, trong đó dịch vụ lưu trữ đơn giản của Amazon (Amazon S3) có lẽ là nổi tiếng nhất. Bài báo này trình bày việc thiết kế và triển khai Dynamo, một kho lưu trữ dữ liệu phân tán có tính sẵn sàng cao và có khả năng mở rộng được xây dựng cho nền tảng của Amazon. Dynamo được sử dụng để quản lý trạng thái của các dịch vụ có yêu cầu độ tin cậy rất cao và cần kiểm soát chặt chẽ sự cân bằng giữa tính khả dụng, tính nhất quán, hiệu quả về chi phí và hiệu năng. Nền tảng của Amazon có rất nhiều ứng dụng đa dạng với các yêu cầu lưu trữ khác nhau. Một bộ ứng dụng yêu cầu phải có một công nghệ lưu trữ đủ linh hoạt để cho phép các nhà thiết kế ứng dụng cấu hình lưu trữ dữ liệu một cách hợp lý dựa trên những cân bằng này để đạt được tính sẵn sàng cao và hiệu năng được đảm bảo theo cách có hiệu quả nhất về chi phí. Có rất nhiều dịch vụ trên nền tảng của Amazon chỉ cần truy cập khóa chính vào một kho dữ liệu. Đối với nhiều dịch vụ, chẳng hạn như những dịch vụ cung cấp danh sách người bán tốt nhất, giỏ hàng, sở thích của khách hàng, quản lý phiên giao dịch, xếp hạng bán hàng và danh mục sản phẩm, mô hình phổ biến là sử dụng cơ sở dữ liệu quan hệ sẽ dẫn đến sự không hiệu quả, giới hạn quy mô và tính sẵn sàng. Dynamo cung cấp một giao diện khóa chính đơn giản để đáp ứng các yêu cầu của các ứng dụng này. Dynamo sử dụng kết hợp các kỹ thuật nổi tiếng để đạt được khả năng mở rộng và tính sẵn có: Dữ liệu được phân chia và sao lưu bằng cách sử dụng hàm băm ổn định (consistent hashing - hàm băm mà việc thêm hoặc bớt một khối dữ liệu (slot) không làm thay đổi đáng kể ánh xạ từ khóa tới các khối dữ liệu) [10], và tính nhất 1
  2. 2. quán được thực hiện dễ dàng bởi object versioning (Cho phép quản lý, lưu trữ nhiều phiên bản của một đối tượng) [12]. Tính nhất quán giữa các bản sao trong quá trình cập nhật được duy trì bởi kỹ thuật quorum-like và một giao thức đồng bộ hóa phân quyền. Dynamo là một hệ thống phân cấp hoàn toàn với nhu cầu tối thiểu cho việc quản lý bằng tay. Các kho lưu trữ có thể được thêm vào và gỡ bỏ khỏi Dynamo mà không yêu cầu bất kỳ phân vùng thủ công hoặc phân phối lại. Trong năm qua, Dynamo đã trở thành công nghệ lưu trữ cơ sở cho một số dịch vụ cốt lõi trong nền tảng thương mại điện tử của Amazon. Nó đã có thể mở rộng quy mô và đảm bảo hiệu quả mà không có bất kỳ gián đoạn nào trong mùa mua sắm bận rộn. Ví dụ: dịch vụ duy trì giỏ hàng (Shopping Cart Service) đã phục vụ hàng chục triệu yêu cầu dẫn đến hơn 3 triệu lần thanh toán trong một ngày và dịch vụ quản lý trạng thái phiên làm việc đã xử lý hàng trăm nghìn phiên hoạt động đồng thời. Sự đóng góp chính của công việc này cho cộng đồng nghiên cứu là việc đánh giá các kỹ thuật khác nhau có thể được kết hợp như thế nào để cung cấp một hệ thống có tính sẵn sàng cao. Nó chứng tỏ rằng một hệ thống lưu trữ nhất quán cuối cùng có thể được sử dụng trong sản xuất với các ứng dụng theo nhu cầu. Nó cũng cung cấp cái nhìn sâu sắc trong việc điều chỉnh các kỹ thuật này để đáp ứng các yêu cầu của hệ thống sản xuất với yêu cầu thực hiện rất nghiêm ngặt. Bài báo này có cấu trúc như sau: Phần 2 trình bày bối cảnh và Phần 3 trình bày công việc liên quan. Phần 4 trình bày thiết kế hệ thống và Phần 5 mô tả việc thực hiện. Phần 6 mô tả chi tiết những kinh nghiệm và hiểu biết thu được bằng cách chạy Dynamo trong sản xuất và Phần 7 kết luận bài báo. Có một số chỗ trong bài báo này được thêm thông tin bổ sung có thể phù hợp nhưng những chỗ được bảo vệ do lợi ích kinh doanh của Ama- zon đòi hỏi chúng ta phải giảm bớt mức độ chi tiết. Vì lý do này, độ trễ bên trong và bên ngoài của các trung tâm dữ liệu trong phần 6, tỷ lệ yêu cầu tuyệt đối trong phần 6.2, độ dài và khối lượng công việc trong phần 6.3 được cung cấp thông qua các biện pháp tổng hợp thay vì các chi tiết tuyệt đối. 2 BACKGROUND Nền tảng thương mại điện tử của Amazon bao gồm hàng trăm dịch vụ hoạt động phối hợp với nhau, cung cấp các chức năng khác nhau, từ các đề xuất đến việc hoàn thành đơn đặt hàng để tìm ra gian lận. Mỗi dịch vụ được tiếp xúc thông qua một giao diện được xác định rõ ràng và có thể truy cập qua mạng. Các dịch vụ này được tổ chức trên một cơ sở hạ tầng bao gồm hàng chục nghìn máy chủ nằm trên nhiều trung tâm dữ liệu trên toàn thế giới. Một số dịch vụ này là stateless (không lưu dữ liệu của client trên server) (ví dụ các dịch vụ tổng hợp các phản hồi từ các dịch vụ khác) và một số là stateful (server cần lưu dữ liệu của client) (ví dụ một dịch vụ tạo ra phản hồi bằng cách thực hiện business logic trên trạng thái của nó được lưu trữ trong kho lưu trữ liên tục). Các hệ thống sản xuất truyền thống lưu trữ trạng thái của chúng trong các cơ sở dữ liệu quan hệ. Tuy nhiên, đối với nhiều mô hình lưu trữ trạng thái liên tục, cơ sở dữ liệu quan hệ là một giải pháp bất khả thi. Hầu hết các dịch vụ này chỉ lưu và truy xuất dữ liệu theo khóa chính, không yêu cầu truy vấn phức tạp và quản lý chức năng được cung cấp bởi một RDBMS (Relational Database Management System - Hệ thống quản lý cơ sở dữ liệu quan hệ). Sự dư thừa chức năng này đòi hỏi phần cứng đắt tiền và có nhân viên duy trì hoạt động tay nghề cao, đây là một giải pháp không hiệu quả. Ngoài ra, các công nghệ nhân bản sẵn sàng còn hạn chế và thường chọn sự nhất quán thay vì tính sẵn sàng. Mặc dù nhiều tiến bộ đã được thực hiện trong những năm gần đây, nó vẫn không dễ dàng để mở rộng cơ sở dữ liệu hoặc sử dụng các lược đồ phân vùng thông minh để cân bằng tải. Bài báo này sẽ giới thiệu về Dynamo - một công nghệ lưu trữ dữ liệu có độ sẵn sàng cao đáp ứng nhu cầu của các lớp dịch vụ quan trọng. Dynamo có một giao diện key/ value đơn giản, có tính sẵn sàng cao với một mức nhất quán xác định, hiệu quả trong việc sử dụng tài nguyên của nó và có một lược đồ đơn giản để giải quyết sự tăng trưởng trong kích thước bộ dữ liệu hoặc tỷ lệ yêu cầu. Mỗi dịch vụ sử dụng Dynamo đều chạy Dynamo instance của riêng mình. 2.1 System Assumptions and Requirements Hệ thống lưu trữ cho loại dịch vụ này có các yêu cầu sau: Mô hình truy vấn: đọc và ghi đơn giản đến một mục dữ liệu mà được xác định duy nhất bởi một khóa. Trạng thái được lưu trữ dưới dạng các đối tượng nhị phân được xác định bởi các khóa duy nhất. Không có hoạt động nào thực hiện trên nhiều mục dữ liệu và không cần giản đồ quan hệ. Yêu cầu này dựa trên quan sát rằng một phần đáng kể các dịch vụ của Amazon có thể làm việc với mô hình truy vấn đơn giản này và không cần bất kỳ giản đồ quan hệ nào. Mục tiêu của Dynamo là lưu trữ các ứng dụng có kích thước tương đối nhỏ (Thường ít hơn 1 MB). Thuộc tính ACID: ACID (Atomicity, Consistency, Isolation, Durability) là một tập hợp các thuộc tính đảm bảo cơ sở dữ liệu giao dịch được xử lý đáng tin cậy. Trong cơ sở dữ liệu, một hoạt động logical trên dữ liệu được gọi là một giao dịch. Kinh nghiệm tại Amazon cho thấy rằng các kho dữ liệu cung cấp bảo đảm ACID có xu hướng có sự sẵn sàng thấp. Điều này đã được cả ngành công nghiệp và các học gỉa thừa nhận rộng rãi [5]. Dynamo nhắm mục tiêu ứng dụng hoạt động với tính nhất quán yếu ("C"trong ACID) nếu điều này dẫn đến tính sẵn sàng cao. Dynamo không cung cấp bất kỳ sự bảo đảm cách ly nào và chỉ cho phép cập nhật khoá duy nhất. Hiệu quả: Hệ thống cần phải hoạt động trên một cơ sở hạ tầng phần cứng. Trong nền tảng của Amazon, dịch vụ có các yêu cầu độ trễ nghiêm ngặt nói chung được 2
  3. 3. Hình 1: Service-oriented architecture of Ama- zon’splatform đo bằng 99,9% của sự phân phối. Do sự truy cập của trạng thái đóng một vai trò quan trọng trong hoạt động dịch vụ, hệ thống lưu trữ phải có khả năng đáp ứng các SLA nghiêm ngặt (xem Phần 2.2 bên dưới). Các dịch vụ phải có cấu hình Dynamo sao cho chúng luôn đạt được các yêu cầu về độ trễ và thông lượng. Sự cân bằng được thực hiện, tiết kiệm chi phí, tính khả dụng, và đảm bảo độ bền. Các giả định khác: Dynamo chỉ được sử dụng bởi nội bộ của dịch vụ Amazon. Môi trường hoạt động của nó được giả định là không chống đối và không có yêu cầu bảo mật liên quan như xác thực và ủy quyền. Hơn nữa, vì mỗi dịch vụ sử dụng Dynamo riêng biệt, thiết kế ban đầu của nó nhắm tới một quy mô lên đến hàng trăm máy chủ lưu trữ. Chúng tôi sẽ thảo luận về những hạn chế về khả năng mở rộng của Dynamo và những khả năng mở rộng có thể có trong các phần sau. 2.2 Service Level Agreements (SLA) Để đảm bảo rằng ứng dụng có thể cung cấp các chức năng của nó trong một thời gian bị giới hạn, mỗi sự phụ thuộc vào nền tảng cần phải cung cấp các chức năng của nó với các giới hạn chặt chẽ hơn. Khách hàng và dịch vụ tham gia Thỏa thuận mức dịch vụ (SLA), hợp đồng được đàm phán chính thức khi khách hàng và dịch vụ đồng ý về một số đặc điểm liên quan đến hệ thống, trong đó nổi bật nhất là phân phối tỷ lệ yêu cầu của khách hàng mong đợi cho một API cụ thể và độ trễ dịch vụ dưới những điều kiện đó. Một ví dụ về SLA đơn giản là một dịch vụ đảm bảo rằng nó sẽ cung cấp phản hồi trong vòng 300ms đối với 99,9% yêu cầu cho một khách hàng, cao nhất là 500 yêu cầu mỗi giây. rong cơ sở hạ tầng định hướng dịch vụ phân cấp của Amazon, các SLA đóng một vai trò quan trọng. Ví dụ như yêu cầu trang tới một trong những trang thương mại điện tử thường đòi hỏi công cụ rendering phải xây dựng phản hồi bằng cách gửi yêu cầu tới hơn 150 dịch vụ. Các dịch vụ này thường có nhiều sự phụ thuộc vào các dịch vụ khác, và do đó biểu đồ cuộc gọi của một ứng dụng có nhiều hơn một cấp. Để đảm bảo rằng công cụ hiển thị trang có thể duy trì một ràng buộc rõ ràng về việc phân phối trang mỗi dịch vụ trong chuỗi lời gọi phải tuân thủ điều khoản thực hiện của nó. Hình 1 cho thấy một cái nhìn trừu tượng về kiến trúc nền tảng của Amazon, nơi nội dung động của trang web được tạo ra bởi các thành phần hiển thị trang, từ đó truy vấn nhiều dịch vụ khác. Một dịch vụ có thể sử dụng các kho dữ liệu khác nhau để quản lý trạng thái của nó và những kho dữ liệu này chỉ có thể truy cập được trong phạm vi ranh giới dịch vụ của nó. Một số dịch vụ hoạt động như các công cụ tổng hợp bằng cách sử dụng một số dịch vụ khác để tạo ra một kết quả tổng hợp. Thông thường, các dịch vụ tổng hợp là stateless, mặc dù họ sử dụng bộ nhớ đệm rộng rãi. Một cách tiếp cận phổ biến trong ngành công nghiệp để hình thành một SLA hướng hiệu năng (performance oriented SLA) là mô tả nó bằng trung bình, trung vị và phương sai dự kiến. Tại Amazon chúng tôi đã phát hiện ra rằng các số liệu này không đủ tốt nếu mục tiêu là xây dựng một hệ thống, nơi mà tất cả khách hàng đều có trải nghiệm tốt, thay vì chỉ phần lớn. Ví dụ nếu sử dụng kỹ thuật cá nhân hóa rộng rãi (extensive personalization) thì khách hàng có lịch sử lâu hơn đòi hỏi phải xử lý nhiều hơn, ảnh hưởng đến hiệu suất ở cấp cao của sự phân tán. Một SLA được nêu trong các thời gian phản hồi trung bình hoặc trung vị sẽ không đề cập đến hiệu suất của phân khúc khách hàng quan trọng này. Để giải quyết vấn đề này, ở Amazon, các SLA được thể hiện và đo ở 99.9% của sự phân tán. Sự lựa chọn cho khoảng 99,9% hoặc thậm chí cao hơn đã được thực hiện dựa trên phân tích chi phí và lợi ích cho thấy chi phí tăng đáng kể để cải thiện hiệu suất. Kinh nghiệm với hệ thống sản xuất của Amazon cho thấy rằng phương pháp này cung cấp một trải nghiệm tổng thể tốt hơn so với các hệ thống đáp ứng các SLA được xác định dựa trên trung bình hoặc trung vị. Trong bài báo này, có rất nhiều tài liệu tham khảo về phân bố phần trăm 99,9 này, phản ánh sự tập trung không ngừng của các kỹ sư Amazon từ hiệu quả sự trải nghiệm của khách hàng của khách hàng. Tuy nhiên, những nỗ lực tối ưu hoá về kỹ thuật và tối ưu hoá của Amazon không tập trung vào các mức trung bình. Một số kỹ thuật, chẳng hạn như các điều phối viên cân bằng tải thao tác ghi, hoàn toàn là mục tiêu kiểm soát hiệu suất ở 99.9%. Hệ thống lưu trữ thường đóng một vai trò quan trọng trong việc thiết lập SLA của dịch vụ, đặc biệt nếu busi- ness logic tương đối nhẹ, như trường hợp của nhiều dịch vụ Amazon. Quản lý trạng thái sẽ trở thành thành phần chính của một dịch vụ SLA. Một trong những cân nhắc thiết kế chính của Dynamo là cung cấp dịch vụ kiểm soát các thuộc tính của hệ thống, chẳng hạn như độ bền và tính nhất quán và để cho các dịch vụ tự cân bằng giữa tính năng, hiệu suất và hiệu quả về chi phí. 3
  4. 4. 2.3 Design Considerations Các thuật toán nhân bản dữ liệu được sử dụng trong các hệ thống thương mại truyền thống thực hiện việc điều phối bản sao đồng bộ để cung cấp một interface truy cập dữ liệu nhất quán. Để đạt được mức độ nhất quán này, các thuật toán này buộc phải đánh đổi sự sẵn sàng của dữ liệu để giảm thiểu các lỗi. Ví dụ, thay vì đối phó với sự không chắc chắn về tính đúng đắn của câu trả lời, dữ liệu sẽ không được sẵn sàng cho đến khi hoàn toàn chắc chắn rằng nó là đúng. Từ những cơ sở dữ liệu được sao chép sớm, chúng ta biết rằng khi đối phó với khả năng xảy ra sự cố mạng, tính đồng bộ mạnh mẽ và tính sẵn sàng cao của dữ liệu thì không thể đạt được đồng thời [2, 11]. Vì những hệ thống và ứng dụng như vậy cần phải biết được mục đích nào có thể đạt được dưới những điều kiện nào. Đối với các hệ thống mà máy chủ và mạng dễ bị lỗi, tính sẵn sàng có thể được tăng lên bằng cách sử dụng các kỹ thuật nhân bản lạc quan (optimistic replication tech- niques), nơi mà những thay đổi được phép truyền sang các bản sao trong background, đồng thời, việc ngắt kết nối được dung thứ. Thách thức với cách tiếp cận này là nó có thể dẫn đến các thay đổi mâu thuẫn (conflicting changes) phải được phát hiện và giải quyết. Quá trình giải quyết xung đột này đưa ra hai vấn đề: khi nào giải quyết và ai sẽ giải quyết chúng. Dynamo được thiết kế để trở thành một kho dữ liệu nhất quán cuối cùng (even- tually consistent); đó là tất cả các cập nhật đến tất cả các bản sao cuối cùng. Việc xem xét thiết kế quan trọng là quyết định thời điểm tiến hành quá trình giải quyết xung đột cập nhật, tức là, các xung đột nên được giải quyết trong quá trình đọc hoặc viết. Nhiều kho dữ liệu truyền thống thực hiện giải quyết xung đột trong quá trình viết và duy trì sự phức tạp của việc đọc đơn giản. Trong các hệ thống như vậy, việc cập nhật có thể bị từ chối nếu kho dữ liệu không thể tiếp xúc được với tất cả (hoặc phần lớn) các bản sao tại một thời điểm nhất định. Mặt khác, Dynamo nhắm đến thiết kế một không gian lưu trữ dữ liệu "luôn ghi được"(nghĩa là một kho dữ liệu sẵn sàng cao cho thao tác viết). Đối với một số dịch vụ của Amazon, từ chối cập nhật khách hàng có thể dẫn đến trải nghiệm của khách hàng kém. Ví dụ: dịch vụ giỏ hàng phải cho phép khách hàng thêm và xóa các mặt hàng khỏi giỏ hàng của họ ngay cả khi mạng và máy chủ bị lỗi. Yêu cầu này buộc chúng ta phải đẩy sự phức tạp của việc giải quyết xung đột đến các thao tác đọc để đảm bảo rằng các các thao tác ghi không bao giờ bị từ chối. Lựa chọn thiết kế tiếp theo là người thực hiện quá trình giải quyết xung đột. Điều này có thể được thực hiện bởi kho dữ liệu hoặc ứng dụng. Nếu giải quyết xung đột được thực hiện bởi các kho dữ liệu, sự lựa chọn của nó là khá hạn chế. Trong trường hợp đó, kho lưu trữ dữ liệu chỉ có thể sử dụng các chính sách đơn giản, chẳng hạn như "Viết lần cuối cùng"("last write wins"), để giải quyết các bản cập nhật mâu thuẫn. Mặt khác, kể từ khi ứng dụng nhận thức được giản đồ dữ liệu, nó có thể quyết định phương pháp giải quyết xung đột phù hợp nhất với trải nghiệm của khách hàng. Ví dụ: ứng dụng duy trì giỏ hàng của khách hàng có thể chọn để "hợp nhất"các phiên bản xung đột và trả lại một giỏ hàng hợp nhất. Mặc dù tính linh hoạt này, một số nhà phát triển ứng dụng có thể không muốn viết ra các cơ chế giải quyết mâu thuẫn của riêng họ và chọn đẩy nó xuống các kho dữ liệu, từ đó chọn một chính sách đơn giản như "Viết lần cuối cùng". Các nguyên tắc chính được chấp nhận trong thiết kế là: • Tăng khả năng mở rộng: Dynamo nên có khả năng mở rộng ra một host lưu trữ (sau đó gọi là "nút") tại một thời điểm, với tác động tối thiểu đối với các thao tác của hệ thống. • Tính đối xứng: Mỗi nút trong Dynamo nên có cùng một bộ trách nhiệm; không nên có nút đặc biệt hoặc nút có vai trò đặc biệt hoặc thêm một bộ trách nhiệm. Theo kinh nghiệm của chúng tôi, tính đối xứng đơn giản hóa quá trình cung cấp và bảo trì hệ thống. • Phân quyền: Sự mở rộng đối xứng, thiết kế nên ưu tiên các kỹ thuật phân quyền ngang hàng (peer-to- peer) thay vì kiểm soát tập trung. Trong quá khứ, kiểm soát tập trung đã dẫn đến sự cố và mục tiêu là để tránh nó càng nhiều càng tốt. Điều này dẫn đến một hệ thống đơn giản, có thể mở rộng hơn và sẵn sàng. • Tính không đồng nhất: Hệ thống cần phải có khả năng khai thác sự không đồng nhất trong cơ sở hạ tầng nó chạy. ví dụ. Việc phân phối công việc phải tỉ lệ thuận với khả năng của các máy chủ cá nhân. Đây là điều cần thiết trong việc thêm các nút mới có dung lượng cao hơn mà không phải nâng cấp tất cả các máy chủ cùng một lúc. 3 RELATED WORK 3.1 Peer to Peer Systems Có một vài hệ thống ngang hàng(P2P) đã xem xét vấn đề lưu trữ và phân tán dữ liệu. Thế hệ đầu tiên của hệ thống P2P, như Freenet và Gnutella, được sử dụng phần lớn như các hệ thống chia sẻ tệp tin. Đây là những ví dụ về mạng không cấu trúc P2P nơi các overlay link giữa các peer được thiết lập một cách tùy ý. Trong các mạng đó, một câu truy vấn tìm kiếm thường tràn(flood) thông qua network để tìm các peer chia sẻ dữ liệu nhiều nhất có thể. Các hệ thống P2P đã phát triển sang thế hệ tiếp theo thành những hệ thống được biết đến rộng rãi như các mạng P2P có cấu trúc. Các mạng này sử dụng một giao thức nhất quán toàn cục để đảm bảo rằng bất kỳ nút nào có thể định tuyến một truy vấn tìm kiếm một cách hiệu quả tới các peer chứa dữ liệu phù hợp. Các hệ thống như Pastry [16] và Chord [20] sử dụng các cơ chế định tuyến để đảm bảo rằng các truy vấn có thể được trả lời trong một số lượng lớn các bước nhảy. Để giảm độ trễ thêm vào được sinh ra bởi việc định tuyến đa bước nhảy, 4
  5. 5. một số hệ thống P2P (ví dụ [14]) sử dụng định tuyến O(1), trong đó mỗi peer duy trì đủ thông tin định tuyến cục bộ để nó có thể định tuyến các yêu cầu (để truy cập một thành phần dữ liệu) tới các peer thích hợp trong một hằng số các bước nhảy. Các hệ thống lưu trữ đa dạng (Various storage systems), ví dụ như Oceanstore [9] và PAST [17] được xây dựng trên các bề mặt định tuyến hàng đầu, Oceanstore cung cấp một dịch vụ lưu trữ toàn cầu, giao dịch, nhất quán, hỗ trợ các cập nhật nối tiếp trên dữ liệu sao lưu lớn. Để cho phép những cập nhật đồng thời trong việc tránh nhiều vấn đề riêng với khóa khu vực(wide-area locking), nó sử dụng một mô hình cập nhật dựa trên các giải quyết xung đột. Các giải quyết xung đột được giới thiệu trong [21] để giảm số lượng hủy các giao dịch. Oceanstore giải quyết các xung đột bằng việc xử lý một loạt các cập nhật, việc chọn trật tự giữa chúng, và sau đó áp dụng chúng một cách thông dụng theo thứ tự đó. Nó được xây dựng cho một môi trường nơi dữ liệu được nhân bản trong một cơ sở hạ tầng không tin cậy. Bằng việc so sánh, PAST cung cấp một tầng trừu tượng đơn giản trên đầu Pastry cho các đối tượng nhất quán và không thay đổi. Nó giả định rằng các ứng dụng có thể xây dựng các ngữ nghĩa lưu trữ cần thiết (như các tập tin có thể thay đổi) trên đầu của nó. 3.2 Distributed File Systems and Databases Việc phân tán dữ liệu cho hiệu năng, tính sẵn sàng và độ bền được nghiên cứu rộng rãi trong cộng đồng hệ thống tệp tin và hệ thống cơ sở dữ liệu. So sánh với các hệ thống lưu trữ P2P nơi chỉ hỗ trợ các không gian tên phẳng thì hệ thống tệp tin phân tán hỗ trợ đặc thù cho các không gian tên phân cấp. Các hệ thống như Ficus [15] và Coda [19] nhân bản các tệp tin cho sự sẵn sàng cao với chi phí nhất quán. Cập nhật các xung đột thường được quản lý bằng các thủ tục giải quyết xung đột cụ thể. Hệ thống Farsite [1] là một hệ thống tệp phân tán không sử dụng bất kì máy chủ trung tâm nào như NFS (Network File System). Farsite đạt được tính sẵn sàng và tính mở rộng cao bằng việc sử dụng nhân bản. Hệ thống tệp GOOGLE(Google File System) [6] là một hệ thống tệp tin phân tán khác được xây dựng cho việc lưu trữ các trạng thái của các ứng dụng nội bộ của Google. GFS sử dụng một thiết kế đơn giản với một siêu máy chủ đơn cho việc làm chủ toàn bộ các siêu dữ liệu(metadata) và nơi các dữ liệu được chia nhỏ thành các khối dữ liệu(chunk) và được lưu trữ trên các máy chủ khối(chunkserver). Bayou là một hệ thống cơ sở dữ liệu quan hệ phân tán cho phép các hoạt động bị ngừng kết nối và cung cấp sự nhất quán dữ liệu cuối cùng (eventual data consistency). Giữa các hệ thống này, Bayou, Coda và Ficus cho phép hoạt động bị ngừng kết nối và có khả năng phục hồi các vấn đề như sự ngưng cung cấp hoặc sự ngắt mạng. Những hệ thống này phân biệt bởi các thủ tục giải quyết xung đột của chúng. Chẳng hạn như , Coda và Ficus Hình 2: Partitioning and replication of keys in Dynamo ring. thực thi giải quyết xung đột cấp hệ thống, và Bayou cho phép các giải pháp cấp ứng dụng. Tất cả chúng, tuy nhiên, bảo đảm nhất quán cuối cùng. Tương tự các hệ thống này, Dynamo cho phép các tác vụ đọc và ghi có thể tiếp tục ngay cả khi phân mảnh mạng (network partitions) và giải quyết các xung đột cập nhật sử dụng các cơ chế giải quyết xung đột khác nhau. Hệ thống lưu trữ blocknhư FAB [18] chia các đối tượng có kích thước lớn thành các khối nhỏ hơn và lưu trữ mỗi khối trong một manner có tính sẵn sàng cao. Trong sự so sánh các hệ thống này, một bản lưu trữ dạng key-value phù hợp hơn trong trường hợp này bởi vì: (a) Nó được chủ ý lưu trữ các đối tượng nhỏ một cách tương đối (kích thước < 1M) và (b) các bản ghi key-value dễ dàng thiết lập cấu hình trên cơ sở mỗi ứng dụng. Antiquity là một hệ thống lưu trữ phân tán rộng được thiết kế để xử lý lỗi xảy ra ở máy chủ [23]. Nó sử dụng secure log để bảo toàn tính toàn vẹn dữ liệu, sao chép mỗi log trên nhiều máy chủ đảm bảo độ bền và sử dụng giao thức chống lỗi của Byzantine để đảm bảo tính nhất quán dữ liệu. Khác với Antiquity, Dynamo không tập trung vào vấn đề toàn vẹn và bảo mật dữ liệu và được xây dựng cho một môi trường tin cậy. Bigtable là một hệ thống lưu trữ phân tán cho việc quản lý dữ liệu có cấu trúc. Nó duy trì một bản đồ(map) thưa, đa chiều và cho phép các ứng dụng truy cập các dữ liệu đa thuộc tính [2]. So sánh với Bigtable, Dynamo nhắm tới các ứng dụng đòi hỏi chỉ truy cập key/value với sự tập trung chủ yếu vào tính sẵn sàng cao, nơi các cập nhật không bị từ chối ngay cả khi phân mảnh mạng hay các lỗi máy chủ. Các hệ thống cơ sở dữ liệu quan hệ truyền thống tập trung vào vấn đề toàn vẹn dữ liệu sao lưu. Mặc dù tính nhất quán mạnh mẽ cung cấp cho nhà phát triển ứng dựng một mô hình lập trình tiện lợi nhưng các hệ thống này bị giới hạn khả năng mở rộng và tính sẵn sàng [7]. Các hệ thống này không có năng lực xử lý các phân mảnh mạng bởi vì chúng thường cung cấp sự đảm bảo tính nhất quán mạnh mẽ. 3.3 Discussion Dynamo khác với các hệ thống lưu trữ phân cấp nói trên theo yêu cầu mục tiêu của nó. Đầu tiên, Dynamo được 5
  6. 6. nhắm mục tiêu chủ yếu tại các ứng dụng cần kho dữ liệu “luôn ghi” (always writeable) nơi không có cập nhật nào bị từ chối bởi vì lỗi hay ghi không đồng thời. Đây là một yêu cầu quan trọng đối với nhiều ứng dụng của Amazon. Thứ hai, như đã đề cập trước đó, Dynamo được xây dựng cho một cơ sở hạ tầng trong 1 miền quản trị duy nhất nơi tất cả các nút được cho là đáng tin cậy. Thứ ba, các ứng dụng sử dụng Dynamo không yêu cầu sự hỗ trợ cho các không gian tên phân cấp (1 tiêu chuẩn trong nhiều hệ thống tệp tin) hoặc lược đồ quan hệ phức tạp (được hỗ trợ bởi các cơ sở dữ liệu truyền thống). Thứ tư, Dynamo được xây dựng cho các ứng dụng nhạy cảm với độ trễ đòi hỏi ít nhất 99,9% hoạt động đọc và ghi được thực hiện trong vòng vài trăm mili giây. Để đáp ứng các yêu cầu độ trễ nghiêm ngặt này, bắt buộc chúng ta phải tránh định tuyến yêu vầu thông qua nhiều nút (thiết kế điển hình được thông qua bởi một số hệ thống bảng băm phân phối như Chord and Pastry). Điều này là do sự định tuyến đa bước nhảy làm thời gian phản hồi tăng lên biến thiên, do đó tăng độ trễ tại ở phần trăm cao hơn. Dynamo có thể được mô tả như một zero-hop DHT (Distributed Hash Table), nơi mỗi nút duy trì đủ thông tin định tuyến cục bộ để định tuyến 1 yêu cầu đến nút tương thích một cách trực tiếp. 4 SYSTEM ARCHITECTURE Kiến trúc của 1 hệ thống lưu trữ cần hoạt động trong một môi trường sản xuất phức tạp. Ngoài các thành phần toàn vẹn dữ liệu thực tế, hệ thống cần có khả năng mở rộng và các giải pháp mạnh mẽ để cân bằng tải, quản lý các thành viên, phát hiện lỗi, phục hồi lỗi, đồng bộ bản sao, xử lý quá tải, truyền trạng thái, truy cập đồng thời, lập kế hoạch công việc, phân phối yêu cầu, định tuyến yêu cầu, điều hành hệ thống và báo động, quản lý cấu hình. Việc mô tả chi tiết từng giải pháp là không thể, do đó bài báo này tập trung vào các kỹ thuật phân phối cốt lõi được sử dụng trong Dynamo: phân vùng, nhân bản, phiên bản, quản lý thành viên, xử lý lỗi và mở rộng. 4.1 System Interface Dynamo lưu trữ các đối tượng liên kết với một khóa thông qua một interface đơn giản; nó đưa ra 2 tác vụ: get() và put(). Hành động get(key) xác định đối tượng nhân bản liên quan đến khóa trong hệ thống lưu trữ và trả về 1 đối tượng hay 1 danh sách các đối tượng với các phiên bản mâu thuẫn trong cùng một ngữ cảnh. Hành động put(key, context, object) xác định nơi các bản sao của đối tượng nên được đặt dựa vào associated key, và ghi các bản sao vào ổ đĩa. Bối cảnh (context) mã hóa siêu dữ liệu hệ thống về đối tượng không rõ ràng cho lời gọi và bao gồm các thông tin như phiên bản của đối tượng. Thông tin ngữ cảnh (context) được lưu trữ cùng với đối tượng để hệ thống có thể xác minh tính hợp lệ của đối tượng ngữ cảnh được cung cấp trong yêu cầu put. Dynamo xử lý cả khoá và đối tượng được cung cấp bởi Vấn đề Công nghệ Lợi ích Phân vùng (Partition- ing) Hàm băm nhất quán (Consistent Hashing) Tăng khả năng mở rộng Tính sẵn sàng cao cho các tác vụ ghi Đồng hồ vector và các phiên bản của dữ liệu Kích thước phiên bản được tách riêng khỏi tỷ lệ cập nhật. Xử lý các lỗi tạm thời Sloppy Quorum và chuyển tiếp gợi ý Cung cấp khả năng sẵn sàng cao và đảm bảo độ bền khi một số bản sao không sẵn sàng. Phục hồi sau các lỗi Chống entropy sử dụng cây Merkle Đồng bộ hóa các bản sao khác nhau trong background Quản lý thành viên và phát hiện các lỗi Gossip-based membership protocol và phát hiện thất bại Bảo tồn sự đối xứng và tránh đăng ký tập trung để lưu trữ thông tin thành viên và thông tin về mức độ sống của nút. Bảng 1: Thể hiện tổng quan danh sách kỹ thuật Dynamo sử dụng và lợi ích thiết thực của chúng. lời gọi như là một mảng không rõ ràng của các byte. Nó áp dụng một bảng băm MD5 trên khóa để sinh ra một định danh 128-bit, được sử dụng để xác định các nút lưu trữ có trách nhiệm phục vụ khoá. 4.2 Partitioning Algorithm Một trong những yêu cầu thiết kế khóa của Dynamo là nó phải mở rộng nhanh chóng. Điều này đòi hỏi một cơ chế nhằm phân vùng dữ liệu một cách tự động qua một tập hợp các nút (i.e. các máy lưu trữ) trong hệ thống. Sơ đồ phân vùng của Dynamo dựa trên hàm băm nhất quán để phân phối tải trên nhiều máy lưu trữ. Trong hàm băm nhất quán [10], phạm vi đầu ra (output range) của một hàm băm được coi như là một không gian cố định tròn hoặc "vòng"(i.e. giá trị băm lớn nhất bao bọc(wrap) quanh giá trị băm nhỏ nhất). Mỗi nút trong hệ thống được gán một giá trị ngẫu nhiên trong không gian này đại diện cho "vị trí"của nó trên vòng. Mỗi mục dữ liệu được xác định bởi một khoá được gán cho một nút bằng cách băm khóa của thành phần dữ liệu để tạo ra vị trí của nó trên vòng, và sau đó đi vòng theo chiều kim đồng hồ để tìm nút đầu tiên với vị trí lớn hơn vị trí của thành phần dữ liệu. Do đó, mỗi nút chịu trách nhiệm cho vùng trong vòng giữa nó và nút hàng xóm trước nó trên vòng. Lợi thế cơ bản của việc băm hợp nhất là sự đi hay đến của một nút chỉ ảnh hưởng đến các hàng xóm liền kề của nó còn các 6
  7. 7. nút khác không bị ảnh hưởng. Thuật toán băm hợp nhất cơ bản thể hiện một số thách thức. Thứ nhất, sự gán vị trí ngẫu nhiên của mỗi nút trên vòng dẫn đến dữ liệu không đồng đều và phân bố tải. Thứ hai, thuật toán cơ bản là không biết đến sự không đồng nhất trong việc thực hiện các nút. Để giải quyết những vấn đề này, Dynamo sử dụng một phiên bản băm hợp nhất (tương tự như hàm băm được sử dụng trong [10, 20]): thay vì ánh xạ một nút tới một điểm duy nhất trong vòng tròn, mỗi nút được gán cho nhiều điểm trong vòng. Để kết thúc, Dynamo sử dụng khái niệm "các nút ảo". Một nút ảo giống như một nút duy nhất trong hệ thống, nhưng mỗi nút có thể chịu trách nhiệm cho nhiều hơn 1 nút ảo. Một cách hiệu quả, khi một nút mới được thêm vào hệ thống, nó được gán nhiều vị trí (henceforth, "tokens") trong vòng. Quá trình tinh chỉnh sơ đồ phân vùng của Dynamo được thảo luận trong Phần 6. Sử dụng các nút ảo có những ưu điểm sau: • Nếu một nút không hoạt động (do lỗi hoặc kiểm tra định kỳ), tải được xử lý bởi nút này sẽ được phân tán đồng đều trên các nút sẵn sàng còn lại. • Khi một nút sẵn sàng trở lại, hoặc một nút mới được thêm vào hệ thống, nút mới sẵn sàng chấp nhận một lượng tải tương đương lượng tải từ mỗi nút sẵn sàng khác. • Số lượng các nút ảo mà một node chịu trách nhiệm có thể được quyết định dựa trên khả năng của nó, việc tính toán cho sự không đồng nhất trong cơ sở hạ tầng vật lý. 4.3 Replication Để đạt được tính sẵn sàng và tính bền cao, Dynamo sao chép các dữ liệu của mình trên nhiều máy chủ. Mỗi mục dữ liệu được sao chép tại N máy, với N là tham số được cấu hình per-instance(cho mỗi trường hợp). Mỗi khóa k được gán cho một nút điều phối viên (được mô tả trong phần trước). Điều phối viên chịu trách nhiệm nhân rộng các mục dữ liệu nằm trong phạm vi của nó. Ngoài việc lưu trữ một cách cục bộ mỗi khóa trong phạm vi của nó, điều phối viên sao chép những khóa đó tại N-1 nút kế tiếp theo chiều kim đồng hồ trong vòng. Điều này dẫn đến một hệ thống mà mỗi nút chịu trách nhiệm cho vùng của vòng giữa nó và Nth hàng xóm phía trước nó. Trong Figure 2, nút B sao chép khóa k tại các nút C và D ngoài việc lưu trữ nó một cách cục bộ. Nút D sẽ lưu các khóa nằm trong phạm vi (A, B], (B, C], và (C, D]. Danh sách các nút chịu trách nhiệm lưu trữ một khóa cụ thể được gọi là danh sách ưu tiên(preference list). Hệ thống được thiết kế, sẽ được giải thích trong phần 4.8, sao cho mọi nút trong hệ thống có thể xác định nút nào ở trong danh sách đó cho bất kỳ khóa cụ thể nào. Để giải quyết các lỗi của nút, danh sách ưu tiên chứa nhiều hơn N nút. Lưu ý rằng, sử dụng các nút ảo, N vị trí kế tiếp đầu tiên cho một khóa cụ thể có thể được sở hữu bởi ít hơn N nút vật lý riêng biệt (tức là một nút có thể chứa nhiều hơn một trong N vị trí đầu tiên) Để giải quyết vấn đề này, Danh sách ưu tiên cho một khóa được xây dựng bằng cách bỏ qua vị trí trong vòng để đảm bảo danh sách chỉ bao gồm các nút vật lý riêng biệt. 4.4 Data Versioning Dynamo cung cấp sự nhất quán cuối cùng, nó cho phép cập nhật được lan truyền đến tất cả các bản sao một cách không đồng bộ. Một lời gọi put() có thể trả về lời gọi của nó trước khi cập nhật đã được áp dụng ở tất cả các bản sao, có thể dẫn đến các kịch bản mà một tác vụ get() tiếp theo có thể trả về một đối tượng không có các bản cập nhật mới nhất. Nếu không có thất bại nào sau đó, sẽ có một ràng buộc về thời gian lan truyền cập nhật. Tuy nhiên, theo các kịch bản lỗi (ví dụ, sự ngừng hoạt động server hay sự phân mảnh network), các bản cập nhật không thể đến được tất cả bản sao trong một khoảng thời gian dài. Có một loại ứng dụng trên nền tảng của Amazon có thể chịu được sự không nhất quán như vậy và có thể được xây dựng để hoạt động trong những điều kiện này. Ví dụ: ứng dụng giỏ hàng yêu cầu thao tác "Thêm vào giỏ hàng"không bao giờ có thể bị lãng quên hoặc bị từ chối. Nếu trạng thái gần đây nhất của giỏ hàng không sẵn sàng và người dùng thay đổi phiên bản cũ của giỏ hàng, sự thay đổi đó vẫn có ý nghĩa và cần được bảo toàn. Nhưng đồng thời, nó không nên thay thế cho trạng thái hiện tại không sẵn sàng của giỏ hàng, vì chính trạng thái hiện tại của giỏ hàng có thể chứa những thay đổi cần được bảo quản. Lưu ý rằng cả hoạt động "thêm vào giỏ hàng"và "xóa sản phẩm từ giỏ hàng"đều được chuyển đổi sang các yêu cầu đặt hàng tới Dynamo. Khi một khách hàng muốn thêm một sản phẩm vào (hoặc xóa khỏi) một giỏ hàng và phiên bản mới nhất không sẵn sàng, sản phẩm sẽ được thêm vào (hoặc đã loại bỏ khỏi) phiên bản cũ hơn và các phiên bản khác nhau được dàn xếp sau đó. Để cung cấp loại bảo đảm này, Dynamo xử lý kết quả của mỗi sự sửa đổi như là một phiên bản mới và không thay đổi phiên bản của dữ liệu. Nó cho phép nhiều phiên bản của một đối tượng có mặt trong hệ thống cùng một lúc. Hầu hết thời gian, các phiên bản mới phụ thuộc vào các phiên bản trước và bản thân hệ thống có thể tự xác định được phiên bản có thẩm quyền (sự kết hợp cú pháp). Tuy nhiên, sự phân nhánh phiên bản có thể xảy ra, với sự hiện diện của các thất bại kết hợp với các bản cập nhật đồng thời, kết quả là các phiên bản xung đột của một đối tượng. Trong các trường hợp này, hệ thống không thể điều chỉnh nhiều phiên bản của cùng một đối tượng và máy khách (client) phải thực hiện việc hòa giải (rec- onciliation) để thu gọn (collapse) nhiều nhánh dữ liệu trở lại thành một. Một ví dụ điển hình về hoạt động col- lapse là "merging"các phiên bản khác nhau của giỏ hàng của khách hàng. Việc sử dụng cơ chế hòa giải (reconcil- iation) này, thao tác "thêm vào giỏ hàng"sẽ không bao giờ bị mất. Tuy nhiên, các sản phẩm đã xóa bị hiển thị lại. Điều quan trọng là phải hiểu rằng các chế độ lỗi nhất định có thể dẫn đến kết quả trong hệ thống không chỉ 7
  8. 8. có hai phiên bản của cùng một dữ liệu. Các cập nhật mà bị phân mảnh mạng hoặc bị lỗi ở nút có thể dẫn đến một đối tượng có các lịch sử phiên bản khác biệt, mà hệ thống sẽ cần phải điều chỉnh trong tương lai. Điều này yêu cầu chúng tôi thiết kế các ứng dụng thừa nhận rõ ràng khả năng có nhiều phiên bản trên cùng một dữ liệu (để không bao giờ mất bất kỳ bản cập nhật nào). Dynamo sử dụng thứ tự đồng hồ vector [12] để nắm bắt quan hệ nhân quả (causality) giữa các phiên bản khác nhau của cùng một đối tượng. Một đồng hồ vector là một danh sách các cặp (node, counter). Một đồng hồ vec- tor được liên kết với mọi phiên bản của mọi đối tượng. Người ta có thể xác định xem hai phiên bản của một đối tượng nằm trên các nhánh song song hoặc có một trình tự nguyên nhân - kết quả, bằng cách kiểm tra đồng hồ vector của chúng. Nếu các counter trên đồng hồ của đối tượng thứ nhất ít hơn hoặc bằng tất cả các node trong đồng hồ thứ hai, thì đối tượng đầu tiên là đến trước đối tượng thứ hai và có thể bị lãng quên. Nếu không, hai thay đổi này được coi là xung đột và cần phải có sự đối chiếu. Trong Dynamo, khi khách hàng muốn cập nhật một đối tượng, nó phải xác định phiên bản nào đang được cập nhật. Điều này được thực hiện bằng cách chuyển ngữ cảnh (context) nó thu được từ một hoạt động đọc trước đó, chứa thông tin đồng hồ vector. Khi xử lý một yêu cầu đọc, nếu Dynamo có quyền truy cập vào nhiều nhánh mà không thể kết hợp các nhánh, nó sẽ trả về tất cả các đối tượng ở nút lá, với thông tin phiên bản tương ứng trong ngữ cảnh (context). Một bản cập nhật bằng cách sử dụng ngữ cảnh này được xem là đã đối chiếu các phiên bản khác nhau và các chi nhánh bị thu gọn thành một phiên bản mới. Để minh hoạ việc sử dụng đồng hồ vector, chúng ta hãy xem xét ví dụ thể hiện trong Figure 3. Một khách hàng ghi một đối tượng mới. Nút (gọi là Sx) xử lý việc ghi cho khóa này làm tăng số thứ tự của nó và sử dụng nó để tạo ra đồng hồ vector của dữ liệu. Hệ thống bây giờ có đối tượng D1 và đồng hồ liên quan của nó [(Sx, 1)]. Khách hàng cập nhật đối tượng. Giả sử cùng một nút xử lý yêu cầu này là tốt. Hệ thống bây giờ cũng có đối tượng D2 và đồng hồ liên quan của nó [(Sx, 2)]. D2 rút xuống từ D1 và do đó ghi đè D1, tuy nhiên có thể có bản sao của D1 kéo dài tại các nút mà chưa thấy D2. Hãy giả sử rằng cùng một khách hàng cập nhật đối tượng một lần nữa và một máy chủ khác (gọi là Sy) xử lý yêu cầu. Hệ thống hiện có dữ liệu D3 và đồng hồ liên quan của nó [(Sx, 2), (Sy, 1)]. Tiếp theo giả sử một khách hàng khác đọc D2 và sau đó cố gắng để cập nhật nó, và một nút khác (gọi là Sz) ghi. Hệ thống hiện có D4 (hậu duệ của D2) có đồng hồ phiên bản là [(Sx, 2), (Sz, 1)]. Một nút được nhận biết D1 hoặc D2 có thể xác định khi nhận D4 và đồng hồ của nó, D1 và D2 sẽ bị ghi đè bởi các dữ liệu mới và có thể được thu gom rác. Một nút nhận biết D3 và nhận được D4 sẽ thấy rằng không có mối quan hệ nhân quả giữa chúng. Nói cách khác, có sự thay đổi trong D3 và D4 mà không được phản ánh trong mỗi nút. Cả hai phiên bản của dữ liệu phải được lưu giữ và trình bày cho cilent (khi đọc) để đối chiếu ngữ nghĩa. Bây giờ giả sử một số client đọc cả D3 và D4 (context sẽ phản ánh rằng cả hai giá trị đã được tìm thấy bằng cách đọc). Bối cảnh của việc đọc là một bản tóm tắt các đồng hồ của D3 và D4, cụ thể là [(Sx, 2), (Sy, 1), (Sz, 1)]. Nếu client thực hiện hòa giải và nút Sx điều phối tác vụ ghi, Sx sẽ cập nhật số thứ tự của nó trong đồng hồ. Dữ liệu mới D5 sẽ có đồng hồ sau: [(Sx, 3), (Sy, 1), (Sz, 1)]. Một vấn đề có thể xảy ra với đồng hồ vector là kích thước của đồng hồ vector có thể phát triển nếu nhiều máy chủ kết hợp ghi cho một đối tượng. Trong thực tế, điều này là không thể bởi vì việc ghi thường được xử lý bởi một trong N nút hàng đầu trong danh sách ưu tiên. Trong trường hợp phân vùng mạng hoặc lỗi của nhiều máy chủ, các yêu cầu ghi có thể được xử lý bởi các nút không nằm trong N nút phía trên trong danh sách các ưu tiên gây ra kích thước của đồng hồ vector tăng lên. Trong các kịch bản này, điều mong muốn là hạn chế kích thước của đồng hồ vector. Để kết thúc điều này, Dynamo sử dụng lược đồ cắt đồng hồ sau đây: Cùng với mỗi cặp (nút, bộ đếm), Dynamo lưu dấu thời gian cho biết lần cuối cùng nút cập nhật dữ liệu. Khi số cặp (nút, đếm) trong đồng hồ vector đạt đến một ngưỡng (giả sử là 10), cặp đôi cũ nhất sẽ được loại bỏ khỏi đồng hồ. Rõ ràng, chương trình cắt ngắn này có thể dẫn đến sự kém hiệu quả trong việc đối chiếu vì mối quan hệ hậu duệ không thể có được chính xác. Tuy nhiên, vấn đề này đã không nổi lên trong sản xuất và do đó vấn đề này đã không được điều tra kỹ lưỡng. 4.5 Execution of get () and put () operations Bất kỳ nút lưu trữ nào trong Dynamo đều đủ điều kiện nhận yêu cầu get và put từ client cho bất kỳ khoá nào. Trong phần này, vì tính đơn giản, chúng tôi mô tả cách các hoạt động này được thực hiện như thế nào trong một môi trường không có sự cố và trong phần tiếp theo chúng ta mô tả các thao tác đọc và ghi được thực hiện như thế nào trong thời gian lỗi. Cả hai thao tác get và put được gọi bằng cách sử dụng framework xử lý yêu cầu cụ thể về cơ sở hạ tầng của Amazon thông qua HTTP. Có hai chiến lược mà client có thể sử dụng để chọn một nút: (1) định tuyến yêu cầu của nó thông qua một bộ cân bằng tải chung, nó sẽ chọn một nút dựa trên thông tin nạp/tải, hoặc (2) sử dụng thư viện client nhận diện phân vùng (partition-aware client library), các yêu cầu định tuyến trực tiếp đến các nút điều phối thích hợp. Lợi thế của cách tiếp cận đầu tiên là client không phải liên kết bất kỳ mã nào cụ thể tới Dynamo trong ứng dụng của nó, trong khi chiến lược thứ hai có thể đạt được độ trễ thấp hơn vì nó bỏ qua bước chuyển tiếp tiềm năng. Một nút xử lý một tác vụ đọc hoặc ghi được gọi là điều phối viên (coordinator). Thông thường, đây là nút đầu tiên trong số N nút hàng đầu trong danh sách ưu tiên. Nếu yêu cầu được nhận thông qua bộ cân bằng tải, các 8
  9. 9. yêu cầu truy cập khóa có thể được chuyển đến bất kỳ nút ngẫu nhiên nào trong vòng. Trong trường hợp này, nút nhận được yêu cầu sẽ không phối hợp nó nếu nút không nằm trong top N trong danh sách ưu tiên của khoá được yêu cầu. Thay vào đó, nút đó sẽ chuyển yêu cầu tới nút đầu tiên trong số N nút hàng đầu trong danh sách ưu tiên. Các tác vụ đọc và ghi liên quan đến N nút đầu tiên khỏe mạnh trong danh sách ưu tiên, bỏ qua những nút đang bị tắt hoặc không thể tiếp cận. Khi tất cả các nút là đạt yêu cầu(healthy), N nút hàng đầu trong danh sách ưu tiên của khoá được truy cập. Khi có nút lỗi hoặc phân vùng mạng, các nút được xếp hạng thấp hơn trong danh sách ưu tiên được truy cập. Để duy trì tính nhất quán giữa các bản sao của nó, Dynamo sử dụng một giao thức nhất quán tương tự như được sử dụng trong các quorum systems. Giao thức này có hai giá trị cấu hình chính: R và W. R là số nút tối thiểu phải tham gia vào một thao tác đọc thành công. W là số nút tối tiểu phải tham gia vào hoạt động ghi thành công. Đặt R và W sao cho R + W> N sẽ tạo ra một hệ thống quorum. Trong mô hình này, độ trễ của một thao tác get (hoặc put) được quyết định bởi các bản sao R (hoặc W) chậm nhất. Vì lý do này, R và W thường được cấu hình ít hơn N, để cung cấp độ trễ tốt hơn. Khi nhận một yêu cầu put () cho một khoá, điều phối viên sẽ tạo ra đồng hồ vector cho phiên bản mới và ghi phiên bản mới tại địa phương. Sau đó, điều phối viên sẽ gửi phiên bản mới (cùng với đồng hồ vector mới) đến N nút có thể truy cập cao nhất. Nếu ít nhất W-1 nút trả lời sau đó tác vụ ghi được coi là thành công. Tương tự, đối với yêu cầu get (), điều phối viên yêu cầu tất cả các phiên bản hiện có của dữ liệu cho khoá đó từ N nút có thể truy cập cao nhất trong danh sách ưu tiên của khóa đó, và chờ đợi R phản hồi trước khi trả lại kết quả cho client. Nếu điều phối viên kết thúc thu thập nhiều phiên bản của dữ liệu, nó trả về tất cả các phiên bản mà nó cho là không có quan hệ nhân quả. Các phiên bản khác nhau sau đó được reconciled và phiên bản đối chiếu thay thế các phiên bản hiện tại được ghi lại. 4.6 Handling Failures: Hinted Handoff Nếu Dynamo sử dụng một phương pháp tiếp cận quo- rum truyền thống, nó sẽ không sẵn sàng trong trường hợp xảy ra lỗi ở các nút hoặc phân vùng mạng, và sẽ làm giảm độ bền ngay cả trong điều kiện lỗi đơn giản nhất. Để khắc phục điều này, nó không bắt buộc phải có số lượng thành viên tham gia thực hiện (quorum member- ship) nghiêm ngặt và thay vào đó nó sử dụng một "quo- rum lỏng lẻo"(sloppy quorum); Tất cả các hoạt động đọc và ghi được thực hiện trên N nút khỏe mạnh đầu tiên từ danh sách ưu tiên, có thể không phải lúc nào cũng là N nút đầu tiên gặp phải khi đi vòng băm đồng nhất. Xem xét ví dụ về cấu hình Dynamo trong Figure 2 với N = 3. Trong ví dụ này, nếu nút A tạm thời bị tắt hoặc không thể truy cập được trong quá trình ghi, sau đó bản sao thông thường đã tồn tại trên A sẽ được gửi đến nút D. Điều này được thực hiện để duy trì tính sẵn sàng mong muốn và đảm bảo độ bền. Bản sao được gửi đến D sẽ có một gợi ý trong siêu dữ liệu của nó cho thấy nút nào được dự định nhận của bản sao (trong trường hợp này là A). Các nút nhận các bản sao gợi ý sẽ giữ chúng trong một cơ sở dữ liệu cục bộ riêng biệt được quét theo định kỳ. Khi phát hiện ra rằng A đã phục hồi, D sẽ cố gắng chuyển bản sao sang A. Một khi chuyển thành công, D có thể xóa đối tượng khỏi lưu trữ địa phương của nó mà không làm giảm tổng số bản sao trong hệ thống. Sử dụng lệnh chuyển nhượng gợi ý, Dynamo đảm bảo rằng các thao tác đọc và ghi không bị lỗi do nút tạm thời hoặc lỗi mạng. Các ứng dụng cần mức sẵn có cao nhất có thể đặt W = 1, đảm bảo rằng một tác vụ viết được chấp nhận miễn là một nút duy nhất trong hệ thống đã ghi được khóa chính xác đến lưu trữ địa phương của nó. Do đó, yêu cầu ghi chỉ bị từ chối nếu tất cả các nút trong hệ thống không có sẵn. Tuy nhiên, trong thực tế, hầu hết các dịch vụ của Amazon trong sản xuất đặt một W cao hơn để đáp ứng mức độ mong muốn của độ bền. Một thảo luận chi tiết hơn về cấu hình N, R và W như trong phần 6. Điều cần thiết là phải có một hệ thống lưu trữ sẵn sàng cao có thể xử lý sự thất bại của toàn bộ trung tâm dữ liệu. Thất bại trung tâm dữ liệu xảy ra do mất điện, cooling failures, thất bại mạng và thiên tai. Dynamo được cấu hình sao cho mỗi đối tượng được nhân rộng trên nhiều trung tâm dữ liệu. Về bản chất, danh sách ưu tiên của một khoá được xây dựng sao cho các nút lưu trữ được lan truyền trên nhiều trung tâm dữ liệu. Các trung tâm dữ liệu này được kết nối thông qua các liên kết mạng tốc độ cao. Đề án sao chép qua nhiều trung tâm dữ liệu cho phép chúng tôi xử lý toàn bộ sự cố của trung tâm dữ liệu mà không bị mất dữ liệu. 4.7 Handling permanent failures: Replica synchronization Việc chuyển tiếp được gợi ý sẽ hiệu quả nhất nếu hệ thống thành viên thấp và thất bại của nút là tạm thời. Có những kịch bản theo đó bản sao gợi ý trở nên không sẵn sàng trước khi chúng có thể được trả lại nút bản sao gốc. Để xử lý mối đe dọa này và các mối đe dọa khác đối với độ bền, Dynamo thực hiện một giao thức anti-entropy (đồng bộ hóa bản sao) để giữ các bản sao đồng bộ. Để phát hiện sự không nhất quán giữa các bản sao nhanh hơn và để giảm thiểu số lượng dữ liệu được truyền, Dy- namo sử dụng Merkle trees [13]. Một Merkle tree là một cây băm nơi các lá là hàm băm của các giá trị của các khóa cá nhân. Parent nodes cao hơn trong cây là hàm băm của con tương ứng. Ưu điểm chính của Merkle tree là mỗi nhánh của cây có thể được kiểm tra độc lập mà không yêu cầu các nút tải toàn bộ cây hoặc toàn bộ bộ dữ liệu. Hơn nữa, Merkle tree giúp giảm số lượng dữ liệu cần được chuyển giao trong khi kiểm tra sự không nhất quán giữa các bản sao. Ví dụ, nếu các giá trị băm gốc của hai cây bằng nhau, thì các giá trị của các nút lá trong cây bằng nhau và các nút yêu cầu không đồng bộ hóa. Nếu không, nó ngụ ý rằng các giá trị của một 9
  10. 10. số bản sao là khác nhau. Trong các trường hợp như vậy, các nút có thể trao đổi các giá trị băm của nút con và quá trình này tiếp tục cho đến khi nó đến lá của cây, tại thời điểm đó các máy chủ có thể xác định các khóa "không đồng bộ". Merkle tree giảm thiểu số lượng dữ liệu cần được chuyển giao cho đồng bộ hóa và giảm số lần đọc đĩa được thực hiện trong quá trình chống entropy. Dynamo sử dụng Merkle tree để chống entropy như sau: Mỗi nút duy trì một Merkle tree riêng biệt cho mỗi dãy khóa (tập hợp các khóa được bao phủ bởi một nút ảo) nó lưu trữ. Điều này cho phép các nút để so sánh xem các khóa trong một phạm vi khóa được cập nhật. Trong lược đồ này, hai nút trao đổi root của Merkle tree tương ứng với các dãy khóa mà chúng lưu trữ chung. Sau đó, sử dụng lược đồ chuyển đổi cây được mô tả ở trên các nút xác định xem chúng có bất kỳ sự khác biệt nào và thực hiện hành động đồng bộ hóa phù hợp. Bất lợi với kế hoạch này là nhiều phạm vi khóa thay đổi khi một nút tham gia hoặc rời khỏi hệ thống do đó đòi hỏi (các) cây được tính lại. Vấn đề này đã được giải quyết, tuy nhiên, theo sơ đồ phân chia tinh vi được mô tả trong Phần 6.2. 4.8 Membership and Failure Detection 4.8.1 Ring Membership Trong môi trường của Amazon, các nút bị mất (do bị lỗi hoặc bị bảo trì) thường ngắn ngủi nhưng cũng có thể kéo dài. Sự biến mất của nút hiếm khi biểu hiện sự ra đi vĩnh viễn và do đó không nên làm tái cân bằng phân vùng hoặc sửa chữa các bản sao không thể tiếp cận được. Vì những lý do này, nó được coi là thích hợp để sử dụng một cơ chế rõ ràng để khởi tạo sự bổ sung và loại bỏ các nút từ một vòng Dynamo. Một quản trị viên sử dụng một công cụ dòng lệnh hoặc một trình duyệt để kết nối với một nút Dynamo và đưa ra một sự thay đổi thành viên để nối một nút với một vòng hoặc xóa một nút khỏi một vòng. Node phục vụ yêu cầu ghi sự thay đổi thành viên và thời gian của phát hành để lưu trữ liên tục. Các thành viên thay đổi tạo thành một lịch sử bởi vì các nút có thể được gỡ bỏ và thêm lại nhiều lần. Một giao thức dựa trên tin đồn (A gossip-based protocol) truyền bá sự thay đổi thành viên và duy trì nhất quán cuối cùng về tư cách thành viên. Mỗi nút liên lạc với một peer được chọn một cách ngẫu nhiên mỗi giây và hai nút điều chỉnh lịch sử thay đổi thành viên của chúng. Khi nút bắt đầu lần đầu tiên, nó chọn tập hợp các token (các nút ảo trong không gian băm phù hợp) và ánh xạ các nút tới các bộ token tương ứng. Việc ánh xạ được duy trì trên đĩa, ban đầu chỉ chứa nút cục bộ và thiết lập token. Các ánh xạ được lưu trữ tại các nút khác nhau của Dynamo được hòa giải trong cùng một trao đổi để điều chỉnh lịch sử thay đổi thành viên. Do đó, việc phân vùng và thông tin vị trí cũng truyền bá qua giao thức dựa trên tin đồn và mỗi nút lưu trữ đều nhận thức được phạm vi token được xử lý bởi các peer của nó. Điều này cho phép mỗi nút chuyển tiếp các thao tác đọc / ghi của khoá tới đúng tập hợp các nút một cách trực tiếp. 4.8.2 External Discovery Cơ chế được mô tả ở trên có thể tạm thời dẫn đến một vòng Dynamo phân chia hợp lý. Ví dụ, quản trị viên có thể liên hệ với nút A để nối A với vòng, sau đó liên hệ với nút B để nối B với vòng. Trong trường hợp này, các nút A và B mỗi nút sẽ tự coi bản thân là một thành viên của vòng, tuy nhiên cũng không nhận thức được ngay lập tức nút khác. Để ngăn chặn các phân vùng logic, một số nút Dynamo đóng vai trò của seed. Các seed là các nút được phát hiện thông qua một cơ chế bên ngoài và được biết đến với tất cả các nút. Bởi vì tất cả các nút cuối cùng làm hòa các thành viên của chúng với một seed, các phân vùng logic là rất khó xảy ra. Seed có thể thu được từ cấu hình tĩnh hoặc từ một dịch vụ cấu hình. Thông thường seed là các nút đầy đủ chức năng trong vòng Dynamo. 4.8.3 Failure Detection Sự phát hiện lỗi trong Dynamo được sử dụng để tránh những cố gắng liên lạc với những peer không thể truy cập được trong quá trình thực hiện get () và put () và khi chuyển các phân vùng và các bản sao gợi ý. Với mục đích tránh những cố gắng thất bại trong truyền thông, một khái niệm hoàn toàn cục bộ về phát hiện sự thất bại là hoàn toàn đủ: nút A có thể xem nút B không thành công nếu nút B không trả lời các thông điệp của nút A (ngay cả khi B đáp ứng các thông điệp của nút C). Với sự hiện diện của một tỷ lệ ổn định các yêu cầu của client tạo ra truyền thông internode trong vòng Dynamo, một nút A nhanh chóng phát hiện ra rằng một nút B không phản hồi khi B không đáp ứng được một thông điệp; Node A sau đó sử dụng các nút thay thế cho các yêu cầu dịch vụ mà ánh xạ tới phân vùng của B; Một lần thử B để kiểm tra sự phục hồi của nó. Trong trường hợp không có yêu cầu của khách hàng để hướng lưu lượng truy cập giữa hai nút, không nút nào thực sự cần biết liệu nút kia có thể truy cập và đáp ứng được hay không. 4.9 Adding/Removing Storage Nodes Khi một nút mới (gọi là X) được thêm vào hệ thống, nó sẽ được gán một số token được phân tán ngẫu nhiên trên vòng. Đối với mỗi dãy khóa được gán cho nút X, có thể có một số nút (nhỏ hơn hoặc bằng N) hiện đang phụ trách xử lý các khóa nằm trong phạm vi token của nó. Do việc phân bổ các phạm vi khóa cho X, một số các nút hiện tại không có một số khóa của chúng và những nút này chuyển các khóa này sang X. Chúng ta hãy xem xét một kịch bản khởi động đơn giản khi nút X được thêm vào vòng như trong Figure 2 giữa A và B. Khi X được thêm vào hệ thống, nó có nhiệm vụ lưu trữ các khóa trong các dãy (F, G), (G, A, X], kết quả là các nút B, C và D không còn phải lưu trữ các khóa trong các dãy tương ứng này. Vì vậy, các nút B, C, và D sẽ cung cấp và cho tới khi sự xác nhận từ X chuyển một tập các khóa. Khi một node bị gỡ bỏ khỏi hệ thống, việc tái phân bổ các khóa xảy ra trong quá trình ngược lại. 10
  11. 11. Kinh nghiệm thực hiện cho thấy rằng cách tiếp cận này phân phối tải trọng phân tán đồng nhất qua các nút lưu trữ, điều quan trọng là phải đáp ứng được các yêu cầu độ trễ và đảm bảo việc khởi động nhanh. Cuối cùng, bằng cách thêm một vòng xác nhận giữa nguồn và đích, nó sẽ được đảm bảo rằng nút đích không nhận được bất kỳ sự chuyển đổi trùng lặp nào cho một dãy khóa nhất định 5 IMPLEMENTATION Trong Dynamo, mỗi nút lưu trữ có ba thành phần phần mềm chính: yêu cầu phối hợp (request coordination), thành viên và phát hiện lỗi (mebership and failure de- tection), và một công cụ lưu trữ địa phương (local per- sistence engine). Tất cả các components này được im- plemented trong Java. Local persistence component của Dynamo cho phép các engines lưu trữ khác nhau được cắm vào. Các Engines đang được sử dụng là Berkeley Database (BDB) Trans- actional Data Store2, BDB Java Edition, MySQL, và một bộ đệm trong bộ nhớ với kho lưu trữ liên tục. Lý do chính để thiết kế một thành phần persistence có thể cắm được là chọn công cụ lưu trữ phù hợp nhất cho mẫu truy cập của ứng dụng. Ví dụ, BDB có thể xử lý các đối tượng theo thứ tự hàng chục kilobytes trong khi MySQL có thể xử lý các đối tượng có kích thước lớn hơn. Các ứng dụng chọn công cụ lưu trữ địa phương của Dynamo dựa trên phân bố kích thước đối tượng của chúng. Phần lớn các trường hợp sản xuất của Dynamo sử dụng BDB Transactional Data Store. Request coordination componen được xây dựng trên một nền tảng thông điệp theo sự kiện, nơi mà đường dẫn xử lý thông điệp (message processing pipeline) được chia thành nhiều giai đoạn tương tự như kiến trúc SEDA [24]. Tất cả các thông tin liên lạc được thực hiện bằng cách sử dụng các kênh Java NIO. Điều phối viên thực hiện các yêu cầu đọc và ghi thay cho client bằng cách thu thập dữ liệu từ một hoặc nhiều nút (trong trường hợp đọc) hoặc lưu trữ dữ liệu tại một hoặc nhiều nút (trong trường hợp ghi). Mỗi yêu cầu của client sẽ tạo ra một máy trạng thái (state machine) trên nút mà nhận được yêu cầu của client. Máy trạng thái chứa tất cả các logic để xác định các nút chịu trách nhiệm về khoá, gửi yêu cầu, chờ phản hồi, có khả năng thực hiện lại, xử lý các phản hồi và đóng gói câu trả lời cho client. Mỗi máy trạng thái xử lý chính xác một yêu cầu của khách hàng. Ví dụ, một thao tác đọc thực hiện máy trạng thái sau đây: (i) gửi yêu cầu đọc đến các nút, (ii) chờ đợi số lượng yêu cầu phản hồi tối thiểu, (iii) nếu quá ít phản hồi đã nhận được trong một thời gian nhất định bị ràng buộc, yêu cầu thất bại, (iv) nếu không (nhận được đủ số lượng phản hồi cần thiết) thu thập tất cả các phiên bản dữ liệu và xác định những người sẽ được trả lại và (v) nếu phiên bản được kích hoạt, thực hiện hòa giải cú pháp và tạo ra một bối cảnh viết không rõ ràng (opaque write context) có chứa các đồng hồ vector mà bao hàm tất cả các phiên bản còn lại. Vì lý do ngắn gọn việc xử lý sự cố và các trạng thái thử lại được bỏ qua. Hình 3: Sự so sánh hiệu suất của độ trễ 99,9% đối với ghi có đệm so với không đệm trong vòng 24 giờ. Khoảng cách giữa các đường liên tiếp trong trục x tương ứng với một giờ Sau khi trả lời câu trả lời cho người gọi, máy đợi một khoảng thời gian nhỏ để nhận được bất kỳ phản hồi nào. Nếu các phiên bản cũ đã được trả lại trong bất kỳ phản hồi nào, điều phối viên sẽ cập nhật các nút đó bằng phiên bản mới nhất. Quá trình này được gọi là read repair vì nó sửa các bản sao mà đã bỏ qua một bản cập nhật gần đây và giải phóng các giao thức chống entropy khỏi việc phải làm điều đó. Như đã lưu ý trước đó, yêu cầu ghi được phối hợp bởi một trong N nút đầu trong danh sách ưu tiên. Mặc dù nó luôn mong muốn có nút đầu tiên trong top N để phối hợp việc ghi dữ liệu để tuần tự hóa tất cả các văn bản tại một vị trí duy nhất, cách tiếp cận này đã dẫn đến sự phân bố tải không đồng đều dẫn đến vi phạm SLA. Điều này là do tải yêu cầu không được phân bố đều trên các đối tượng. Để chống lại điều này, bất kỳ nút N nào trong danh sách ưu tiên được phép phối hợp viết. Đặc biệt, vì mỗi bài viết thường theo sau một thao tác đọc, điều phối viên cho một bài viết được chọn là nút trả lời nhanh nhất cho thao tác đọc trước đó được lưu trong thông tin ngữ cảnh của yêu cầu. Tối ưu hóa này cho phép chúng ta chọn nút có dữ liệu được đọc bởi thao tác đọc trước đó làm tăng cơ hội nhận được tính nhất quán "đọc-viết của bạn". Nó cũng làm giảm tính biến đổi trong việc thực hiện xử lý yêu cầu để cải thiện hiệu suất ở 99,9 phần trăm. 6 EXPERIENCES & LESSONS LEARNED Dynamo được sử dụng bởi vài dịch vụ với các cấu hình khác nhau. Các trường hợp khác nhau sẽ có các cách giải quyết xung đột và các tham số R, W, N là khác nhau. Sau đây là các mô hình chính trong đó Dynamo được sử dụng: • Sự đối chiếu business login cụ thể: Đây là trường hợp sử dụng phổ biến Dynamo. Mỗi đối tượng dữ liệu được nhân rộng qua nhiều nút. Trong trường hợp các phiên bản khác nhau, ứng dụng client thực hiện logic đối chiếu của nó. Dịch vụ giỏ hàng được thảo luận trước đó là một ví dụ điển hình của thể loại này. Business logic của nó đối chiếu các đối 11
  12. 12. tượng bằng cách hợp nhất các phiên bản khác nhau của giỏ hàng khách hàng. • Sự đối chiếu dựa trên timestamp: Trường hợp này khác với trường hợp trước chỉ ở cơ chế đối chiếu. Trong trường hợp các phiên bản khác nhau, Dy- namo tính logic timestamp đơn giản dựa trên "last write wins"; Tức là, đối tượng có giá trị timestamp vật lý lớn nhất được chọn là phiên bản chính xác. Dịch vụ duy trì thông tin session của khách hàng là một ví dụ điển hình về dịch vụ sử dụng chế độ này. • Máy đọc hiệu suất cao: Trong khi Dynamo được xây dựng để trở thành một kho lưu trữ dữ liệu "al- ways writeable", một vài dịch vụ đang điều chỉnh đặc tính quorum và sử dụng nó như là một máy đọc hiệu suất cao. Thông thường, các dịch vụ này có tỷ lệ yêu cầu đọc cao và chỉ một số lượng nhỏ các cập nhật. Trong cấu hình này, thông thường R được thiết lập = 1 và W = N. Đối với các dịch vụ này, Dy- namo cung cấp khả năng phân vùng và nhân rộng dữ liệu của chúng qua các nút khác nhau do đó đáp ứng khả năng mở rộng lớn. Một số trường hợp này hoạt động như the authoritative cache persistence đối với dữ liệu lưu trữ trong các kho lưu trữ nặng hơn. Những dịch vụ duy trì danh mục sản phẩm và các mặt hàng quảng cáo phù hợp với loại này. Lợi thế chính của Dynamo là các ứng dụng client của nó có thể điều chỉnh các giá trị của N, R và W để đạt được mức độ mong muốn về hiệu suất, tính sẵn sàng và độ bền. Ví dụ, giá trị của N xác định độ bền của mỗi đối tượng. Một giá trị tiêu biểu của N được sử dụng bởi người dùng của Dynamo là 3. Các giá trị của W và R ảnh hưởng tới đối tượng sẵn có, độ bền và tính nhất quán. Ví dụ, nếu W được đặt = 1, hệ thống sẽ không bao giờ từ chối yêu cầu ghi khi có ít nhất một nút trong hệ thống có thể xử lý thành công yêu cầu ghi. Tuy nhiên, các giá trị W và R thấp có thể làm tăng nguy cơ không nhất quán vì các yêu cầu ghi được coi là thành công và được trả lại cho clients ngay cả khi chúng không được xử lý bởi đa số bản sao. Điều này cũng chỉ ra một lỗ hổng (vulnerability window) cho độ bền khi một yêu cầu ghi được trả lại thành công cho khách hàng ngay cả khi nó đã được duy trì ở một số lượng nhỏ các nút. Kinh nghiệm truyền thống cho thấy sự bền bỉ và tính sẵn sàng gắn liền với nhau. Tuy nhiên, điều này không nhất thiết phải đúng ở đây. Ví dụ, lỗ hổng cho độ bền có thể được giảm bằng cách tăng W. Điều này có thể làm tăng xác suất từ chối yêu cầu (do đó giảm tính khả dụng) bởi vì nhiều node lưu trữ cần phải tồn tại để xử lý một yêu cầu ghi. Cấu hình chung (N, R, W) được sử dụng bởi vài trường hợp của Dynamo là (3,2,2). Các giá trị này được chọn để đáp ứng các mức độ cần thiết của hiệu suất, độ bền, tính nhất quán và các SLA sẵn có. Tất cả các phép đo trình bày trong phần này được thực hiện trên một hệ thống sống hoạt động với một cấu hình (3,2,2) và vận hành một trăm cặp nút với các cấu hình Hình 4: Tỉ lệ của các nút không cân bằng (i.e, các nút có tải yêu cầu vượt quá ngưỡng nhất định từ tải hệ thống trung bình) và tải yêu cầu tương ứng của chúng. Khoảng cách giữa các đường trong trục x tương ứng với khoảng thời gian là 30 phút. phần cứng đồng nhất. Như đã đề cập ở trên, mỗi trường hợp của Dynamo chứa các nút nằm trong nhiều trung tâm dữ liệu. Các trung tâm dữ liệu này thường được kết nối thông qua các đường dẫn mạng tốc độ cao. Nhớ lại rằng để tạo ra một phản hồi get (hoặc put) thành công, R (hoặc W) nút cần phải phản hồi đến điều phối viên. Rõ ràng, độ trễ mạng giữa các trung tâm dữ liệu ảnh hưởng đến thời gian phản hồi và các nút (và vị trí trung tâm dữ liệu của chúng) được chọn sao cho các ứng dụng hướng đến các SLAs được đáp ứng. 6.1 Balancing Performance and Durabil- ity Trong khi mục tiêu thiết kế nguyên tắc của Dynamo là xây dựng một kho dữ liệu có sẵn, hiệu năng cao là một tiêu chí quan trọng không kém trên nền tảng của Ama- zon. Như được lưu ý trước đó, để cung cấp trải nghiệm khách hàng nhất quán, dịch vụ của Amazon đặt ra các mục tiêu hiệu năng ở mức phân vị cao hơn (chẳng hạn như 99,9% hoặc 99,99%). Một SLA điển hình được yêu cầu bởi các dịch vụ sử dụng Dynamo là 99,9% các yêu cầu đọc và ghi thực thi trong vòng 300ms. Kể từ khi Dynamo được vận hành trên các thành phần phần cứng tiêu chuẩn có ít thông số I/O hơn các máy chủ doanh nghiệp cao cấp, việc cung cấp hiệu năng cao một cách nhất quán cho hoạt động đọc và ghi là một nhiệm vụ không dễ dàng. Sự tham gia của nhiều nút lưu trữ trong quá trình đọc và ghi làm cho nó trở nên khó khăn hơn, vì hiệu năng của các thao tác này bị giới hạn bởi các bản sao chậm nhất của R hoặc W. Hình 4 cho thấy độ trễ trung bình và độ trễ 99,9% của hoạt động đọc và ghi của Dynamo trong thời gian 30 ngày. Như được thấy trong hình, có sự khác biệt đáng kể trong tỷ lệ yêu cầu giữa ban ngày và ban đêm. Hơn nữa, các độ trễ ghi thì cao hơn độ trễ đọc một cách rõ ràng bởi vì các hoạt động ghi luôn dẫn đến sự truy cập đĩa. Đồng thời, 99,9% độ trễ là khoảng 200ms và là một mức độ cao hơn mức trung bình. Điều này là do 99,9% độ trễ bị ảnh hưởng bởi một số yếu tố như sự thay đổi tải yêu cầu, các kích thước đối tượng và các mô hình địa phương. Trong khi mức độ hiệu năng này là chấp nhận được đối với một số dịch vụ, một vài dịch vụ customer-facing 12
  13. 13. được yêu cầu cao hơn về hiệu suất. Đối với các dịch vụ này, Dynamo cung cấp khả năng đánh đổi sự đảm bảo độ bền cho hiệu suất. Trong việc tối ưu hóa, mỗi nút lưu trữ duy trì một bộ đệm đối tượng trong bộ nhớ chính của nó. Mỗi thao tác ghi được lưu trữ trong bộ đệm và được ghi định kỳ để lưu trữ bởi một writer thread. Trong lược đồ này, các thao tác đọc, đầu tiên sẽ kiểm tra xem khóa được yêu cầu có trong bộ đệm hay không. Nếu có, đối tượng được đọc từ bộ đệm thay vì từ engine lưu trữ. Việc tối ưu hóa này đã làm giảm độ trễ 99,9% xuống 5 lần trong lưu lượng truy cập cao điểm ngay cả đối với một bộ đệm rất nhỏ của một nghìn đối tượng (xem Hình 5). Rõ ràng, lược đồ này có đánh đổi độ bền cho hiệu suất. Trong chương trình này, sự sập máy chủ có thể dẫn đến mất các tác vụ ghi đã được xếp trong bộ đệm. Để giảm rủi ro về độ bền, hoạt động ghi được tinh chế để điều phối viên chọn một trong số các bản sao N để thực hiện một “durable write”(ghi bền vững). Do điều phối viên chỉ chờ đợi W phản hồi, hiệu năng của hoạt động ghi không bị ảnh hưởng bởi hiệu năng của các hoạt động ghi bền vững được thực hiện bởi một bản sao đơn lẻ. 6.2 Ensuring Uniform Load distribution Dynamo sử dụng consistent hashing(băm nhất quán) để phân vùng không gian khóa của nó qua các bản sao và để đảm bảo phân bố tải thống nhất. Một sự phân bố khoá đồng nhất có thể giúp chúng ta đạt được sự phân bố tải đồng đều với giả định rằng sự phân phối quyền truy cập của các khóa không bị chênh lệch nhiều. Đặc biệt, thiết kế của Dynamo giả định rằng ngay cả khi có một skew(sự chênh lệch) đáng kể trong sự phân phối quyền truy cập, có đủ các khóa trong sự kết thúc phổ biến của sự phân phối để tải của việc xử lý các khóa phổ biến có thể được lan truyền qua các nút đồng nhất thông qua việc phân vùng. Phần này thảo luận về sự mất cân bằng tải trong Dynamo và tác động của các chiến lược phân vùng khác nhau đối với sự phân bố tải. Để nghiên cứu sự mất cân bằng tải và tương quan của nó với tải yêu cầu, tổng số các yêu cầu nhận được của mỗi nút đã được đo đạc trong một khoảng thời gian 24 giờ - được chia thành các khoảng thời gian 30 phút. Trong một khoảng thời gian cho trước, một nút được xem là "cân bằng", nếu tải yêu cầu của nút lệch với tải trung bình với một giá trị nhỏ hơn một ngưỡng nhất định(ở đây là 15%). Nếu không, nút này được coi là "không cân bằng". Hình 6 trình bày tỉ lệ của các nút "không cân bằng"(henceforth) trong khoảng thời gian này. Để tham khảo, tải yêu cầu tương ứng nhận được bởi toàn bộ hệ thống trong khoảng thời gian này cũng được vẽ. Như được thể hiện trong hình, tỷ lệ mất cân bằng giảm với việc tải ngày càng tăng. Ví dụ, trong trường hợp tải toàn hệ thống thấp thì tỷ lệ mất cân đối là 20% và trong các trường hợp tải toàn hệ thống cao thì tỉ lệ này chỉ còn gần 10%. Theo trực giác(Một cách chủ quan), điều này có thể được giải thích bằng thực tế, dưới các tải cao, một số lượng lớn các khóa phổ biến được truy cập và nhờ sự phân phối đồng nhất các khóa, tải được phân bố đều. Hình 5: Phần này thảo luận về sơ đồ phân vùng của Dy- namo đã phát triển theo thời gian như thế nào và ý nghĩa của nó đối với việc phân bố tải. Tuy nhiên, trong các tải thấp (nơi tải = 1 / 8 tải được đo cao nhất(tải ở đỉnh)), các khóa phổ biến ít hơn được truy cập, dẫn đến sự mất cân bằng tải cao hơn. Chiến lược 1: T tokens ngẫu nhiên trên mỗi nút và phân vùng theo giá trị token: Đây là chiến lược ban đầu được triển khai trong quá trình sản xuất (và được mô tả trong Phần 4.2). Trong lược đồ này, mỗi nút được gán T tokens (được chọn đồng nhất ngẫu nhiên từ không gian băm). Các token của tất cả các nút được sắp xếp theo giá trị của chúng trong không gian băm. Cứ hai token liên tiếp xác định một phạm vi. Token cuối cùng và token đầu tiên tạo thành một dải "bao bọc"xung quanh từ giá trị cao nhất tới giá trị thấp nhất trong không gian băm. Bởi vì các token được chọn một cách ngẫu nhiên, các phạm vi có giá trị biến đổi về kích thước. Khi các nút tham gia và rời khỏi hệ thống, bộ token sẽ thay đổi và do đó các phạm vi cũng thay đổi. Lưu ý rằng không gian cần thiết để duy trì thành viên tại mỗi nút tăng tuyến tính với số lượng nút trong hệ thống. Trong khi sử dụng chiến lược này, có những vấn đề sau. Thứ nhất, khi một nút mới tham gia vào hệ thống, nó cần "ăn cắp"các phạm vi khóa của nó từ các nút khác. Tuy nhiên, các nút truyền các phạm vi khoá tới nút mới phải scan kho lưu trữ địa phương của chúng để truy xuất tập thích hợp của các mục dữ liệu. Lưu ý rằng việc thực hiện thao tác scan như vậy trên một nút sản xuất thì phức tạp vì các thao tác scan là các thao tác resource intensive và chúng cần được thực hiện ở chế độ nền mà không ảnh hưởng đến hiệu năng khách hàng. Điều này đòi hỏi chúng ta phải thực thi công việc khởi động (bootstrap- ping task) ở mức ưu tiên thấp nhất. Tuy nhiên, điều này làm chậm quá trình khởi động (bootstrapping) và trong mùa mua sắm bận rộn, khi các nút xử lý hàng triệu yêu cầu mỗi ngày, quá trình bootstrapping mất gần một ngày để hoàn thành. Thứ hai, khi một nút tham gia/rời khỏi hệ thống, các phạm vi khóa (key ranges) được xử lý bởi nhiều nút thay đổi và các Merkle tree cho các phạm vi mới cần được tính toán lại, đó là một hành động không đơn giản để thực hiện trên một hệ thống sản xuất. Cuối cùng, không có cách nào dễ dàng để kết xuất toàn bộ không gian khóa do sự ngẫu nhiên trong các phạm vi khóa, và điều này làm cho quá trình lưu trữ trở nên phức tạp. Trong lược đồ này, việc lưu trữ toàn bộ không gian khoá đòi hỏi chúng ta phải lấy các khóa từ mỗi nút riêng biệt, mà điều này thì không hiệu quả. Vấn đề cơ bản với chiến lược này là các lược đồ phân vùng dữ liệu và sắp xếp dữ liệu được đan xen nhau. Ví 13
  14. 14. dụ, trong một số trường hợp, nó được ưu tiên để thêm nhiều hơn các nút vào hệ thống nhằm xử lý sự gia tăng tải yêu cầu. Tuy nhiên, trong ngữ cảnh này, không thể thêm các nút mà không ảnh hưởng đến việc phân vùng dữ liệu. Lý tưởng nhất là nên sử dụng các lược đồ độc lập cho sự phân vùng và đặt vị trí. Để đạt được mục tiêu này, các chiến lược sau đây được đánh giá. Chiến lược 2: T tokens ngẫu nhiên trên mỗi nút và các phân vùng có kích thước bằng nhau: Trong chiến lược này, không gian băm được chia thành Q vùng/phạm vi có kích thước bằng nhau và mỗi nút được gán T tokens ngẫu nhiên. Q thường được thiết lập sao cho Q » N và Q » S*T, trong đó S là số nút trong hệ thống. Trong chiến lược này, các token chỉ được sử dụng để xây dựng các chức năng mà chúng ánh xạ các giá trị trong không gian băm tới các danh sách có thứ tự của các nút và không quyết định phân vùng. Một phân vùng được đặt trên N nút duy nhất đầu tiên gặp trong khi đi trong vòng theo chiều kim đồng hồ từ cuối phân vùng. Hình 7 minh họa chiến lược này với N = 3. Trong ví dụ này, các nút A, B, C gặp phải khi đi trong vòng từ cuối phân vùng chứa khóa k1. Những ưu điểm chính của chiến lược này là: (i) tách phân vùng và phân vùng, và (ii) cho phép khả năng thay đổi lược đồ vị trí trong thời gian chạy. Chiến lược 3: Q/S tokens trên mỗi nút, các phân vùng có kích thước bằng nhau: Tương tự như chiến lược 2, chiến lược này chia không gian băm thành Q phân vùng có kích thước bằng nhau và vị trí của phân vùng được tách rời khỏi lược đồ phân vùng. Hơn nữa, mỗi nút được gán Q/S tokens với S là số nút trong hệ thống. Khi một nút rời khỏi hệ thống, các token của nó được phân phối ngẫu nhiên đến các nút còn lại như vậy các thuộc tính này được bảo toàn. Tương tự như vậy, khi một nút tham gia vào hệ thống, nó "đánh cắp"các token từ các nút trong hệ thống theo cách bảo tồn những đặc tính này. Hiệu quả của ba chiến lược này được đánh giá bằng một hệ thống với S = 30 và N = 3. Tuy nhiên, việc so sánh các chiến lược khác nhau một cách công bằng thì khó vì các chiến lược khác nhau có cấu hình khác nhau để điều chỉnh sự hiệu quả của chúng. Ví dụ: thuộc tính phân phối tải của chiến lược 1 phụ thuộc vào số lượng các to- ken (tức là T), trong khi chiến lược 3 phụ thuộc vào số phân vùng (tức là, Q). Một cách hợp lý để so sánh các chiến lược này là đánh giá sự chênh lệch trong phân bố tải của chúng trong khi tất cả chiến lược sử dụng cùng một khoảng không gian để duy trì thông tin thành viên. Ví dụ, trong chiến lược 1 mỗi nút cần duy trì các vị trí token của tất cả các nút trong vòng và trong chiến lược 3 mỗi nút cần duy trì thông tin về các phân vùng được gán cho mỗi nút. Trong thử nghiệm tiếp theo của chúng tôi, các chiến lược này được đánh giá bằng cách thay đổi các thông số có liên quan (T và Q). Hiệu suất cân bằng tải của mỗi chiến lược được đo cho nhiều kích thước khác nhau của thông tin thành viên cần được duy trì tại mỗi nút, ở đó Hiệu suất cân bằng tải(Load balanc- ing efficiency) được định nghĩa là tỷ lệ số yêu cầu trung bình của từng nút tới số lượng yêu cầu tối đa bởi các nút hottest. Hình 6: So sánh hiệu quả phân bố tải của các chiến lược khác nhau đối với hệ thống với 30 nút và N = 3 với số lượng bằng nhau của siêu dữ liệu duy trì ở mỗi nút. Các giá trị của kích thước hệ thống và số lượng các bản sao được dựa trên cấu hình điển hình được triển khai cho phần lớn các dịch vụ Các kết quả được đưa ra trong Hình 8. Như đã thấy trong hình, chiến lược 3 đạt được hiệu quả cân bằng tải tốt nhất và chiến lược 2 có hiệu quả cân bằng tải tồi tệ nhất. Trong một thời gian ngắn, Chiến lược 2 phục vụ như một thiết lập tạm thời trong quá trình của việc migrating các instance của Dynamo từ việc sử dụng Chiến lược 1 đến Chiến lược 3. So với Chiến lược 1, Chiến lược 3 đạt được hiệu quả tốt hơn và giảm kích thước thông tin thành viên duy trì ở mỗi nút. Trong khi kho lưu trữ không phải là vấn đề lớn thì các nút này lan truyền thông tin thành viên theo định kỳ và như vậy là cần thiết để giữ cho thông tin này càng gọn nhẹ càng tốt. Ngoài ra, chiến lược 3 là thuận lợi và đơn giản hơn để triển khai vì những lý do sau: (i) Khởi động/Phục hồi nhanh hơn: Vì các phân vùng được cố định, chúng có thể được lưu trữ trong các tệp tin riêng biệt, có nghĩa là một phân vùng có thể được thay đổi vị trí như một đơn vị bằng việc trao đổi các tập tin một cách đơn giản(tránh các truy cập ngẫu nhiên cần thiết để xác định vị trí cụ thể). Điều này đơn giản hóa quá trình khởi động và phục hồi. (ii) Dễ lưu trữ: Việc lưu trữ định kỳ tập dữ liệu là yêu cầu bắt buộc đối với hầu hết các dịch vụ lưu trữ Amazon. Việc lưu trữ toàn bộ tập dữ liệu mà chúng được lưu trữ bởi Dynamo đơn giản hơn trong chiến lược 3 bởi vì các tệp phân vùng có thể được lưu trữ riêng lẻ. Trái lại, trong Chiến lược 1, các token được chọn ngẫu nhiên và lưu trữ dữ liệu được lưu trữ trong Dynamo đòi hỏi phải lấy khóa từ các nút riêng biệt và thường không hiệu quả và chậm. Bất lợi của chiến lược 3 là việc thay đổi nút thành viên đòi hỏi sự điều phối để bảo vệ các thuộc tính được yêu cầu của assignment. 6.3 Divergent Versions: When and How Many? Như đã nói ở trên, Dynamo được thiết kế để cân bằng tính sẵn có. Để hiểu sự tác động chính xác của các lỗi khác nhau trên sự nhất quán, dữ liệu chi tiết được yêu cầu trên nhiều yếu tố: thời lượng gián đoạn, loại thất bại, độ tin cậy của thành phần, khối lượng công việc vv 14

×