6.1 Trận chiến viết tắt: BASE vs. AXIT

"Trong hóa học, pH đo độ axit tương đối của dung dịch nước. Thang đo pH chạy từ 0 (các chất có tính axit mạnh) đến 14 (các chất có tính kiềm mạnh); nước tinh khiết ở 25°C có độ pH là 7 và trung tính.

Các kỹ sư dữ liệu đã sử dụng phép ẩn dụ này để so sánh các cơ sở dữ liệu về độ tin cậy của các giao dịch."

Có lẽ, ý tưởng là thế này: độ pH càng cao, tức là. cơ sở dữ liệu càng gần với "kiềm" ("BASE"), các giao dịch càng kém tin cậy.

Cơ sở dữ liệu quan hệ phổ biến, chẳng hạn như MySQL, chỉ xuất hiện trên cơ sở ACID. Nhưng trong mười năm qua, cái gọi là cơ sở dữ liệu NoSQL, kết hợp một số loại cơ sở dữ liệu rất khác nhau dưới tên này, đã hoạt động khá tốt mà không cần ACID. Trên thực tế, có một số lượng lớn các nhà phát triển làm việc với cơ sở dữ liệu NoSQL và hoàn toàn không quan tâm đến các giao dịch và độ tin cậy của chúng. Hãy xem họ có đúng không nhé.

Bạn không thể nói chung chung về cơ sở dữ liệu NoSQL, bởi vì nó chỉ là một bản tóm tắt tốt. Các cơ sở dữ liệu NoSQL khác nhau trong thiết kế của các hệ thống con lưu trữ dữ liệu và thậm chí trong các mô hình dữ liệu: NoSQL vừa là CouchDB hướng tài liệu vừa là biểu đồ Neo4J. Nhưng nếu chúng ta nói về chúng trong bối cảnh giao dịch, thì tất cả chúng đều có xu hướng giống nhau ở một điểm: chúng cung cấp các phiên bản hạn chế về tính nguyên tử và sự cô lập, do đó không cung cấp bảo đảm ACID. Để hiểu điều này có nghĩa là gì, hãy trả lời câu hỏi: họ cung cấp cái gì, nếu không phải ACID? Không có gì?

Không thực sự. Xét cho cùng, chúng cũng giống như cơ sở dữ liệu quan hệ, cũng cần bán mình trong một gói đẹp. Và họ đã nghĩ ra chữ viết tắt "hóa học" của riêng mình - BASE.

6.2 BASE với tư cách là nhân vật phản diện

Và ở đây một lần nữa, tôi sẽ không đi theo thứ tự các chữ cái, mà tôi sẽ bắt đầu với thuật ngữ cơ bản - tính nhất quán. Tôi sẽ phải cân bằng hiệu ứng nhận dạng của bạn, bởi vì tính nhất quán này ít liên quan đến tính nhất quán từ ACID. Vấn đề với thuật ngữ nhất quán là nó được sử dụng trong quá nhiều ngữ cảnh. Nhưng tính nhất quán này có bối cảnh sử dụng rộng hơn nhiều, và thực sự đây chính xác là tính nhất quán được thảo luận khi thảo luận về các hệ thống phân tán.

Các cơ sở dữ liệu quan hệ mà chúng ta đã nói ở trên cung cấp các mức cô lập giao dịch khác nhau và mức nghiêm ngặt nhất trong số đó đảm bảo rằng một giao dịch không thể nhìn thấy các thay đổi không hợp lệ được thực hiện bởi một giao dịch khác. Nếu bạn đang đứng ở quầy thanh toán trong một cửa hàng, và tại thời điểm đó, tiền thuê được rút khỏi tài khoản của bạn, nhưng giao dịch chuyển tiền thuê không thành công và tài khoản của bạn trở lại giá trị trước đó (tiền là không được ghi nợ), thì giao dịch thanh toán của bạn khi thanh toán sẽ không được mọi người chú ý đến những cử chỉ này - xét cho cùng, giao dịch đó chưa bao giờ được thực hiện và dựa trên yêu cầu cách ly giao dịch, các giao dịch khác không thể nhận thấy những thay đổi tạm thời của nó.

Nhiều cơ sở dữ liệu NoSQL bỏ qua đảm bảo cách ly và cung cấp "tính nhất quán cuối cùng", theo đó cuối cùng bạn sẽ thấy dữ liệu hợp lệ, nhưng có khả năng giao dịch của bạn sẽ đọc các giá trị không hợp lệ - nghĩa là tạm thời hoặc được cập nhật một phần hoặc lỗi thời. Có thể dữ liệu sẽ trở nên nhất quán ở chế độ "lười biếng" khi đọc ("lazily at read time").

NoSQL được hình thành như một cơ sở dữ liệu để phân tích thời gian thực và để đạt được tốc độ cao hơn, họ đã hy sinh tính nhất quán. Và Eric Brewer, người đã đặt ra thuật ngữ BASE, đã xây dựng cái gọi là "định lý CAP", theo đó:

Đối với bất kỳ triển khai tính toán phân tán nào, có thể cung cấp không quá hai trong số ba thuộc tính sau:

  • tính nhất quán của dữ liệu ( tính nhất quán ) - dữ liệu trên các nút (trường hợp) khác nhau không mâu thuẫn với nhau;
  • tính khả dụng ( tính khả dụng ) - bất kỳ yêu cầu nào đối với hệ thống phân tán đều kết thúc bằng phản hồi chính xác, nhưng không đảm bảo rằng phản hồi của tất cả các nút hệ thống đều giống nhau;
  • dung sai phân vùng (dung sai phân vùng ) - Ngay cả khi không có kết nối giữa các nút, chúng vẫn tiếp tục hoạt động độc lập với nhau.

Nếu bạn muốn một lời giải thích rất đơn giản về CAP, thì đây.

Có ý kiến ​​​​cho rằng định lý CAP không hoạt động và thường được xây dựng quá trừu tượng. Bằng cách này hay cách khác, cơ sở dữ liệu NoSQL thường từ chối tính nhất quán trong ngữ cảnh của định lý CAP, mô tả tình huống sau: dữ liệu đã được cập nhật trong một cụm với một số phiên bản, nhưng các thay đổi vẫn chưa được đồng bộ hóa trên tất cả các phiên bản. Hãy nhớ rằng, tôi đã đề cập đến ví dụ về DynamoDB ở trên, ví dụ này cho tôi biết: các thay đổi của bạn trở nên lâu bền - đây là HTTP 200 dành cho bạn - nhưng tôi chỉ thấy các thay đổi sau 10 giây? Một ví dụ khác từ cuộc sống hàng ngày của nhà phát triển là DNS, Hệ thống tên miền. Nếu ai chưa biết thì đây đích thị là “từ điển” dịch (các) địa chỉ http thành địa chỉ IP.

Bản ghi DNS đã cập nhật được truyền đến các máy chủ theo cài đặt khoảng thời gian lưu vào bộ đệm ẩn - vì vậy các bản cập nhật không được chú ý ngay lập tức. Chà, một sự không nhất quán về thời gian tương tự (tức là, cuối cùng là tính nhất quán) có thể xảy ra với một cụm cơ sở dữ liệu quan hệ (ví dụ: MySQL) - xét cho cùng, tính nhất quán này không liên quan gì đến tính nhất quán từ ACID. Do đó, điều quan trọng là phải hiểu rằng theo nghĩa này, cơ sở dữ liệu SQL và NoSQL không có nhiều khác biệt khi nói đến một số phiên bản trong một cụm.

Ngoài ra, tính nhất quán từ đầu đến cuối có thể có nghĩa là các yêu cầu ghi sẽ được thực hiện không theo thứ tự: nghĩa là tất cả dữ liệu sẽ được ghi, nhưng giá trị nhận được cuối cùng sẽ không phải là giá trị cuối cùng trong hàng đợi ghi.

Cơ sở dữ liệu Non-ACID NoSQL có cái gọi là "trạng thái mềm" do mô hình nhất quán từ đầu đến cuối, có nghĩa là trạng thái của hệ thống có thể thay đổi theo thời gian, ngay cả khi không có đầu vào. Nhưng các hệ thống như vậy cố gắng cung cấp khả năng tiếp cận lớn hơn. Cung cấp tính khả dụng 100% không phải là một nhiệm vụ tầm thường, vì vậy chúng tôi đang nói về “tính khả dụng cơ bản”. Và cùng với ba khái niệm này: “về cơ bản có sẵn”, “trạng thái mềm” (“trạng thái mềm”) và “tính nhất quán cuối cùng” tạo thành từ viết tắt BASE.

Thành thật mà nói, khái niệm BASE đối với tôi dường như là một trình bao bọc tiếp thị trống rỗng hơn ACID - bởi vì nó không cung cấp bất kỳ điều gì mới và không đặc trưng cho cơ sở dữ liệu theo bất kỳ cách nào. Và việc gắn nhãn (ACID, BASE, CAP) vào một số cơ sở dữ liệu nhất định chỉ có thể gây nhầm lẫn cho các nhà phát triển. Dù sao thì tôi cũng quyết định giới thiệu cho bạn thuật ngữ này vì rất khó bỏ qua nó khi nghiên cứu cơ sở dữ liệu, nhưng bây giờ bạn đã biết nó là gì, tôi muốn bạn quên nó đi càng sớm càng tốt. Và hãy quay trở lại khái niệm cô lập.

6.3 Vậy cơ sở dữ liệu BASE hoàn toàn không đáp ứng tiêu chí ACID?

Về cơ bản, nơi cơ sở dữ liệu ACID khác với cơ sở dữ liệu không phải ACID là cơ sở dữ liệu không phải ACID thực sự bỏ qua sự cô lập. Điều này là quan trọng để hiểu. Nhưng điều quan trọng hơn là phải đọc tài liệu cơ sở dữ liệu và kiểm tra chúng theo cách mà những người từ dự án Hermitage đã làm. Việc những người tạo ra cơ sở dữ liệu này hay cơ sở dữ liệu kia gọi đứa con tinh thần của họ chính xác như thế nào - ACID hay BASE, CAP hay không CAP không quá quan trọng. Điều quan trọng là cơ sở dữ liệu này hoặc cơ sở dữ liệu đó cung cấp chính xác những gì.

Nếu những người tạo cơ sở dữ liệu tuyên bố rằng nó cung cấp các đảm bảo về ACID, thì có thể có lý do cho việc này, nhưng bạn nên tự mình kiểm tra để hiểu liệu điều này có đúng như vậy không và ở mức độ nào. Nếu họ tuyên bố rằng cơ sở dữ liệu của họ không cung cấp những đảm bảo như vậy, thì điều này có thể có nghĩa là những điều sau:

  • DB không đảm bảo tính nguyên tử. Mặc dù một số cơ sở dữ liệu NoSQL cung cấp API riêng cho các hoạt động nguyên tử (ví dụ: DynamoDB);

  • DB không cung cấp bảo đảm cách ly. Ví dụ, điều này có nghĩa là cơ sở dữ liệu sẽ không ghi dữ liệu theo thứ tự mà chúng được ghi.

Đối với việc đảm bảo độ bền, nhiều cơ sở dữ liệu thỏa hiệp về điểm này vì lợi ích của hiệu suất. Ghi vào đĩa là một thao tác quá lâu và có một số cách để giải quyết vấn đề này. Tôi không muốn đi sâu vào lý thuyết cơ sở dữ liệu, nhưng để bạn hiểu đại khái nên xem xét theo cách nào, tôi sẽ mô tả một cách chung chung cách các cơ sở dữ liệu khác nhau giải quyết vấn đề về độ bền.

Để so sánh các cơ sở dữ liệu khác nhau, trong số những thứ khác, bạn cần biết cấu trúc dữ liệu nào làm cơ sở cho hệ thống con lưu trữ và truy xuất dữ liệu của một cơ sở dữ liệu cụ thể. Tóm lại: các cơ sở dữ liệu khác nhau có cách triển khai lập chỉ mục khác nhau - nghĩa là tổ chức truy cập dữ liệu. Một số trong số chúng cho phép bạn ghi dữ liệu nhanh hơn, số khác - đọc dữ liệu nhanh hơn. Nhưng không thể nói chung chung rằng một số cấu trúc dữ liệu làm cho độ bền cao hơn hoặc thấp hơn.

6.4 các cơ sở dữ liệu khác nhau lập chỉ mục dữ liệu như thế nào và điều này ảnh hưởng đến độ bền như thế nào, v.v.

Có hai cách tiếp cận chính để lưu trữ và truy xuất dữ liệu.

Cách dễ nhất để lưu dữ liệu là thêm các thao tác vào cuối tệp theo cách giống như nhật ký (nghĩa là luôn xảy ra thao tác chắp thêm): không thành vấn đề nếu chúng ta muốn thêm, thay đổi hoặc xóa dữ liệu - tất cả Các thao tác CRUD được ghi đơn giản vào nhật ký. Tìm kiếm nhật ký là không hiệu quả và đó là lúc chỉ mục xuất hiện - một cấu trúc dữ liệu đặc biệt lưu trữ siêu dữ liệu về chính xác nơi dữ liệu được lưu trữ. Chiến lược lập chỉ mục đơn giản nhất cho nhật ký là bản đồ băm theo dõi các khóa và giá trị. Các giá trị sẽ là tham chiếu đến byte offset cho dữ liệu được ghi bên trong tệp, là nhật ký (log) và được lưu trữ trên đĩa. Cấu trúc dữ liệu này được lưu trữ hoàn toàn trong bộ nhớ, trong khi bản thân dữ liệu nằm trên đĩa và được gọi là cây LSM (hợp nhất cấu trúc nhật ký).

Bạn có thể tự hỏi: nếu chúng ta viết các hoạt động của mình vào nhật ký mọi lúc, thì nó sẽ phát triển một cách chóng mặt? Có, và do đó, kỹ thuật nén đã được phát minh, giúp "dọn sạch" dữ liệu theo một số chu kỳ, cụ thể là chỉ để lại giá trị phù hợp nhất cho mỗi khóa hoặc xóa nó. Và nếu chúng tôi có nhiều hơn một nhật ký trên đĩa, nhưng nhiều nhật ký và tất cả chúng đều được sắp xếp, thì chúng tôi sẽ nhận được một cấu trúc dữ liệu mới có tên SSTable (“bảng chuỗi được sắp xếp”) và điều này chắc chắn sẽ cải thiện hiệu suất của chúng tôi. Nếu chúng ta muốn sắp xếp trong bộ nhớ, chúng ta sẽ nhận được một cấu trúc tương tự - cái gọi là MemTable, nhưng với nó, vấn đề là nếu xảy ra sự cố cơ sở dữ liệu nghiêm trọng, thì dữ liệu được ghi cuối cùng (nằm trong MemTable, nhưng chưa được ghi vào đĩa) bị mất. Thực ra,

Một cách tiếp cận khác để lập chỉ mục dựa trên B-tree (“B-tree”). Trong cây B, dữ liệu được ghi vào đĩa trong các trang có kích thước cố định. Các khối dữ liệu này thường có kích thước khoảng 4 KB và có các cặp khóa-giá trị được sắp xếp theo khóa. Một nút B-tree giống như một mảng với các liên kết đến một loạt các trang. tối đa. số lượng liên kết trong một mảng được gọi là hệ số nhánh. Mỗi phạm vi trang là một nút cây B khác có liên kết đến các phạm vi trang khác.

Cuối cùng, ở cấp độ trang tính, bạn sẽ tìm thấy các trang riêng lẻ. Ý tưởng này tương tự như con trỏ trong các ngôn ngữ lập trình cấp thấp, ngoại trừ việc các tham chiếu trang này được lưu trữ trên đĩa chứ không phải trong bộ nhớ. Khi XÁC NHẬN và XÓA xảy ra trong cơ sở dữ liệu, thì một số nút có thể tách thành hai cây con để khớp với hệ số phân nhánh. Nếu cơ sở dữ liệu bị lỗi vì bất kỳ lý do nào trong quá trình, thì tính toàn vẹn của dữ liệu có thể bị xâm phạm. Để ngăn điều này xảy ra, cơ sở dữ liệu sử dụng cây B duy trì "nhật ký ghi trước" hoặc WAL, trong đó mọi giao dịch đơn lẻ đều được ghi lại. WAL này được sử dụng để khôi phục trạng thái của cây B nếu nó bị hỏng. Và có vẻ như đây là điều làm cho cơ sở dữ liệu sử dụng cây B tốt hơn về độ bền. Nhưng cơ sở dữ liệu dựa trên LSM cũng có thể duy trì một tệp về cơ bản thực hiện cùng chức năng như WAL. Do đó, tôi sẽ lặp lại những gì tôi đã nói và có lẽ hơn một lần: hiểu cơ chế hoạt động của cơ sở dữ liệu bạn đã chọn.

Tuy nhiên, điều chắc chắn về cây B là chúng rất tốt cho tính giao dịch: mỗi khóa chỉ xuất hiện ở một vị trí trong chỉ mục, trong khi các hệ thống con lưu trữ nhật ký có thể có nhiều bản sao của cùng một khóa trong các phân đoạn khác nhau (ví dụ: lần nén tiếp theo được thực hiện).

Tuy nhiên, thiết kế của chỉ mục ảnh hưởng trực tiếp đến hiệu suất của cơ sở dữ liệu. Với cây LSM, việc ghi vào đĩa là tuần tự và cây B gây ra nhiều lần truy cập đĩa ngẫu nhiên, vì vậy thao tác ghi với LSM nhanh hơn so với cây B. Sự khác biệt đặc biệt quan trọng đối với các ổ đĩa cứng từ tính (HDD), trong đó ghi tuần tự nhanh hơn nhiều so với ghi ngẫu nhiên. Việc đọc chậm hơn trên các cây LSM vì bạn phải xem qua một số cấu trúc dữ liệu và bảng SS khác nhau ở các giai đoạn nén khác nhau. Chi tiết hơn nó trông như thế này. Nếu chúng ta thực hiện một truy vấn cơ sở dữ liệu đơn giản với LSM, trước tiên chúng ta sẽ tra cứu khóa trong MemTable. Nếu nó không có ở đó, chúng tôi xem SSTable gần đây nhất; nếu không có, thì chúng tôi xem SSTable áp chót, v.v. Nếu khóa được yêu cầu không tồn tại, thì với LSM, chúng tôi sẽ biết điều này sau cùng. Cây LSM được sử dụng trong, ví dụ: LevelDB, RocksDB, Cassandra và HBase.

Tôi mô tả tất cả chi tiết như vậy để bạn hiểu rằng khi chọn một cơ sở dữ liệu, bạn cần cân nhắc nhiều thứ khác nhau: ví dụ: bạn có muốn ghi hoặc đọc dữ liệu nhiều hơn không. Và tôi vẫn chưa đề cập đến sự khác biệt trong các mô hình dữ liệu (bạn có cần duyệt qua dữ liệu, vì mô hình biểu đồ cho phép không? Có bất kỳ mối quan hệ nào giữa các đơn vị khác nhau trong dữ liệu của bạn không - khi đó cơ sở dữ liệu quan hệ sẽ ra tay giải cứu?), và 2 loại lược đồ dữ liệu - khi viết (như trong nhiều NoSQL) và đọc (như trong quan hệ).

Nếu chúng ta quay lại khía cạnh độ bền, thì kết luận sẽ như sau: bất kỳ cơ sở dữ liệu nào ghi vào đĩa, bất kể cơ chế lập chỉ mục, đều có thể đảm bảo tốt cho độ bền của dữ liệu, nhưng bạn cần xử lý từng cơ sở dữ liệu cụ thể , chính xác những gì nó cung cấp.

6.5 Cơ sở dữ liệu trong bộ nhớ hoạt động như thế nào

Nhân tiện, ngoài cơ sở dữ liệu ghi vào đĩa, còn có cái gọi là cơ sở dữ liệu "trong bộ nhớ" hoạt động chủ yếu với RAM. Nói tóm lại, cơ sở dữ liệu trong bộ nhớ thường cung cấp độ bền thấp hơn vì tốc độ ghi và đọc nhanh hơn, nhưng điều này có thể phù hợp với một số ứng dụng.

Thực tế là bộ nhớ RAM từ lâu đã đắt hơn đĩa, nhưng gần đây nó đã bắt đầu nhanh chóng trở nên rẻ hơn, điều này đã tạo ra một loại cơ sở dữ liệu mới - hợp lý, với tốc độ đọc và ghi dữ liệu từ RAM. Nhưng bạn sẽ hỏi ngay: còn sự an toàn dữ liệu của các cơ sở dữ liệu này thì sao? Ở đây một lần nữa, bạn cần xem xét các chi tiết của việc thực hiện. Nói chung, các nhà phát triển cơ sở dữ liệu như vậy cung cấp các cơ chế sau:

  • Bạn có thể sử dụng RAM chạy bằng pin;
  • Có thể ghi nhật ký thay đổi vào đĩa (giống như WAL đã đề cập ở trên), nhưng bản thân dữ liệu thì không;
  • Bạn có thể ghi định kỳ các bản sao của trạng thái cơ sở dữ liệu vào đĩa (không sử dụng các tùy chọn khác, không đảm bảo mà chỉ cải thiện độ bền);
  • Bạn có thể sao chép trạng thái của RAM sang các máy khác.

Ví dụ: cơ sở dữ liệu Redis trong bộ nhớ, chủ yếu được sử dụng làm hàng đợi tin nhắn hoặc bộ đệm ẩn, thiếu độ bền từ ACID: nó không đảm bảo rằng một lệnh được thực hiện thành công sẽ được lưu trữ trên đĩa, vì Redis xóa dữ liệu vào đĩa (nếu bạn đã bật tính năng kiên trì) chỉ không đồng bộ, theo các khoảng thời gian đều đặn.

Tuy nhiên, điều này không quan trọng đối với tất cả các ứng dụng: Tôi đã tìm thấy một ví dụ về trình soạn thảo trực tuyến hợp tác của EtherPad, trình soạn thảo này bị xóa cứ sau 1-2 giây và có khả năng người dùng có thể mất một vài chữ cái hoặc một từ, điều này hầu như không quan trọng. Mặt khác, vì cơ sở dữ liệu trong bộ nhớ tốt ở chỗ chúng cung cấp các mô hình dữ liệu khó thực hiện với các chỉ mục đĩa, Redis có thể được sử dụng để thực hiện các giao dịch - hàng đợi ưu tiên của nó cho phép bạn thực hiện điều này.