Mô hình / thuật toán đồng bộ hóa máy khách-máy chủ?


224

Tôi có cảm giác rằng phải có các mẫu đồng bộ hóa máy khách-máy chủ ngoài kia. Nhưng tôi hoàn toàn thất bại trong việc lên google.

Tình huống khá đơn giản - máy chủ là nút trung tâm, có nhiều máy khách kết nối và thao tác cùng một dữ liệu. Dữ liệu có thể được phân chia trong các nguyên tử, trong trường hợp có xung đột, bất cứ thứ gì trên máy chủ, đều được ưu tiên (để tránh khiến người dùng rơi vào giải quyết xung đột). Đồng bộ hóa một phần được ưa thích do lượng dữ liệu lớn.

Có bất kỳ mô hình / thực tiễn tốt cho tình huống như vậy, hoặc nếu bạn không biết về bất kỳ - cách tiếp cận của bạn là gì?

Dưới đây là cách tôi nghĩ bây giờ để giải quyết nó: Song song với dữ liệu, một tạp chí sửa đổi sẽ được tổ chức, có tất cả các giao dịch được đánh dấu thời gian. Khi máy khách kết nối, nó sẽ nhận được tất cả các thay đổi kể từ lần kiểm tra cuối cùng, ở dạng hợp nhất (máy chủ sẽ duyệt qua danh sách và xóa các bổ sung theo sau là xóa, hợp nhất các bản cập nhật cho mỗi nguyên tử, v.v.). Et voila, chúng tôi đang cập nhật.

Thay thế sẽ là giữ ngày sửa đổi cho mỗi bản ghi và thay vì thực hiện xóa dữ liệu, chỉ cần đánh dấu chúng là đã xóa.

Có suy nghĩ gì không?


27
đồng ý có rất ít thảo luận về các kiểu mẫu cho loại điều này ... mặc dù kịch bản này khá phổ biến
Jack Ukleja

Câu trả lời:


88

Bạn nên nhìn vào cách quản lý thay đổi phân phối hoạt động. Nhìn vào SVN, CVS và các kho lưu trữ khác quản lý deltas hoạt động.

Bạn có một số trường hợp sử dụng.

  • Đồng bộ hóa các thay đổi. Cách tiếp cận thay đổi nhật ký (hoặc lịch sử delta) của bạn có vẻ tốt cho việc này. Khách hàng gửi deltas của họ đến máy chủ; máy chủ hợp nhất và phân phối đồng bằng cho khách hàng. Đây là trường hợp điển hình. Cơ sở dữ liệu gọi đây là "nhân rộng giao dịch".

  • Khách hàng đã mất đồng bộ hóa. Hoặc thông qua một bản sao lưu / khôi phục hoặc do một lỗi. Trong trường hợp này, máy khách cần lấy trạng thái hiện tại từ máy chủ mà không cần thông qua deltas. Đây là một bản sao từ tổng thể đến chi tiết, deltas và hiệu suất bị nguyền rủa. Đó là một lần duy nhất; khách hàng bị hỏng; đừng cố tối ưu hóa điều này, chỉ cần thực hiện một bản sao đáng tin cậy.

  • Khách hàng nghi ngờ. Trong trường hợp này, bạn cần so sánh máy khách với máy chủ để xác định xem máy khách có được cập nhật hay không và cần bất kỳ đồng bằng nào.

Bạn nên tuân theo mẫu thiết kế cơ sở dữ liệu (và SVN) để đánh số tuần tự mỗi thay đổi. Bằng cách đó, khách hàng có thể đưa ra một yêu cầu tầm thường ("Tôi nên có bản sửa đổi nào?") Trước khi thử đồng bộ hóa. Và thậm chí sau đó, truy vấn ("Tất cả deltas kể từ năm 2149") rất đơn giản để khách hàng và máy chủ xử lý.


Ông có thể giải thích chính xác một delta là gì? Tôi đoán đó là sự kết hợp băm / dấu thời gian ... Tôi muốn nghe từ bạn.
Anis

Một delta đề cập đến sự thay đổi giữa hai phiên bản. Ví dụ: nếu tên người dùng đã thay đổi thì đồng bằng có thể giống như {revision: 123, name: "John Doe"}
dipole_moment

31

Là một phần của nhóm, tôi đã thực hiện khá nhiều dự án liên quan đến đồng bộ hóa dữ liệu, vì vậy tôi nên có thẩm quyền trả lời câu hỏi này.

Đồng bộ hóa dữ liệu là một khái niệm khá rộng và có quá nhiều thứ để thảo luận. Nó bao gồm một loạt các cách tiếp cận khác nhau với những mặt trái và mặt trái của chúng. Dưới đây là một trong những phân loại có thể dựa trên hai quan điểm: Đồng bộ / Không đồng bộ, Máy khách / Máy chủ / Ngang ngang hàng. Việc thực hiện đồng bộ hóa phụ thuộc rất nhiều vào các yếu tố này, độ phức tạp của mô hình dữ liệu, lượng dữ liệu được truyền và lưu trữ và các yêu cầu khác. Vì vậy, trong mỗi trường hợp cụ thể, sự lựa chọn nên có lợi cho việc triển khai đơn giản nhất đáp ứng các yêu cầu ứng dụng.

Dựa trên đánh giá về các giải pháp sẵn có, chúng tôi có thể phân định một số lớp đồng bộ hóa chính, khác nhau về độ chi tiết của các đối tượng có thể đồng bộ hóa:

  • Đồng bộ hóa toàn bộ tài liệu hoặc cơ sở dữ liệu được sử dụng trong các ứng dụng dựa trên đám mây, chẳng hạn như Dropbox, Google Drive hoặc Yandex.Disk. Khi người dùng chỉnh sửa và lưu tệp, phiên bản tệp mới được tải lên đám mây hoàn toàn, ghi đè lên bản sao trước đó. Trong trường hợp có xung đột, cả hai phiên bản tệp đều được lưu để người dùng có thể chọn phiên bản nào phù hợp hơn.
  • Đồng bộ hóa các cặp khóa-giá trị có thể được sử dụng trong các ứng dụng có cấu trúc dữ liệu đơn giản, trong đó các biến được coi là nguyên tử, nghĩa là không được chia thành các thành phần logic. Tùy chọn này tương tự như đồng bộ hóa toàn bộ tài liệu, vì cả giá trị và tài liệu đều có thể được ghi đè hoàn toàn. Tuy nhiên, từ góc độ người dùng, một tài liệu là một đối tượng phức tạp bao gồm nhiều phần, nhưng một cặp khóa-giá trị chỉ là một chuỗi ngắn hoặc một số. Do đó, trong trường hợp này, chúng ta có thể sử dụng chiến lược giải quyết xung đột đơn giản hơn, xem xét giá trị phù hợp hơn, nếu đó là lần cuối cùng thay đổi.
  • Đồng bộ hóa dữ liệu có cấu trúc như một cây hoặc biểu đồ được sử dụng trong các ứng dụng phức tạp hơn trong đó lượng dữ liệu đủ lớn để gửi toàn bộ cơ sở dữ liệu mỗi lần cập nhật. Trong trường hợp này, các xung đột phải được giải quyết ở cấp độ của các đối tượng, trường hoặc mối quan hệ riêng lẻ. Chúng tôi chủ yếu tập trung vào tùy chọn này.

Vì vậy, chúng tôi đã nắm được kiến ​​thức của mình trong bài viết này mà tôi nghĩ có thể rất hữu ích cho mọi người quan tâm đến chủ đề => Đồng bộ hóa dữ liệu trong các ứng dụng iOS dựa trên dữ liệu cốt lõi ( http://blog.denivip.ru/index.php/2014/04 / data-syncing-in-core-data-dựa-ios-apps /? lang = en )


3
^ ^ ^ ^ ^ ^ Đây là câu trả lời hay nhất, các bạn!
hgoebl

Tôi đồng ý, Denis đã đưa rất nhiều vào chủ đề + các liên kết bài viết là tuyệt vời. Cũng nói về Cựu ước được đề cập bởi DanielPaull. Trả lời bởi S.Lott là tốt nhưng điều này sâu hơn nhiều.
Kstallian

28

Những gì bạn thực sự cần là Chuyển đổi hoạt động (OT). Điều này thậm chí có thể phục vụ cho các xung đột trong nhiều trường hợp.

Đây vẫn là một lĩnh vực nghiên cứu tích cực, nhưng có nhiều triển khai các thuật toán OT khác nhau xung quanh. Tôi đã tham gia vào nghiên cứu như vậy trong một số năm nay, vì vậy hãy cho tôi biết nếu tuyến đường này làm bạn quan tâm và tôi sẽ vui lòng đưa bạn vào các tài nguyên có liên quan.


7
Daniel, một con trỏ đến các tài nguyên liên quan sẽ được đánh giá cao.
Parand

4
Tôi chỉ đọc lại bài viết trên wikipedia. Nó đi một chặng đường dài và có nhiều tài liệu tham khảo có liên quan ở cuối trang đó. Tôi sẽ chỉ cho bạn công việc của Chengzheng Sun - tác phẩm của ông được tham khảo từ wikipedia. vi.wikipedia.org/wiki/Operational_transatures . Mong rằng sẽ giúp!
Daniel Paull

13

Câu hỏi không rõ ràng, nhưng tôi sẽ xem xét khóa lạc quan nếu tôi là bạn. Nó có thể được thực hiện với một số thứ tự mà máy chủ trả về cho mỗi bản ghi. Khi một khách hàng cố lưu lại bản ghi, nó sẽ bao gồm số thứ tự mà nó nhận được từ máy chủ. Nếu số thứ tự khớp với những gì trong cơ sở dữ liệu tại thời điểm nhận được bản cập nhật, bản cập nhật được cho phép và số thứ tự được tăng lên. Nếu số thứ tự không khớp, bản cập nhật không được phép.


2
Số thứ tự là bạn của bạn ở đây. Hãy suy nghĩ về hàng đợi tin nhắn liên tục.
Daniel Paull

7

Tôi đã xây dựng một hệ thống như thế này cho một ứng dụng khoảng 8 năm trước và tôi có thể chia sẻ một vài cách mà nó đã phát triển khi việc sử dụng ứng dụng đã phát triển.

Tôi đã bắt đầu bằng cách đăng nhập mọi thay đổi (chèn, cập nhật hoặc xóa) từ bất kỳ thiết bị nào vào bảng "lịch sử". Vì vậy, nếu, chẳng hạn, ai đó thay đổi số điện thoại của họ trong bảng "liên hệ", hệ thống sẽ chỉnh sửa trường contact.phone và cũng thêm bản ghi lịch sử với action = update, field = phone, record = [contact ID], giá trị = [số điện thoại mới]. Sau đó, bất cứ khi nào một thiết bị đồng bộ hóa, nó sẽ tải xuống các mục lịch sử kể từ lần đồng bộ hóa cuối cùng và áp dụng chúng vào cơ sở dữ liệu cục bộ của nó. Điều này nghe có vẻ như mô hình "nhân rộng giao dịch" được mô tả ở trên.

Một vấn đề là giữ ID duy nhất khi các mục có thể được tạo trên các thiết bị khác nhau. Tôi không biết về UUID khi tôi bắt đầu điều này, vì vậy tôi đã sử dụng ID tăng tự động và viết một số mã phức tạp chạy trên máy chủ trung tâm để kiểm tra ID mới được tải lên từ thiết bị, thay đổi chúng thành ID duy nhất nếu có xung đột và báo cho thiết bị nguồn thay đổi ID trong cơ sở dữ liệu cục bộ của nó. Chỉ thay đổi ID của các bản ghi mới là không tệ, nhưng nếu tôi tạo, ví dụ: một mục mới trong bảng liên hệ, sau đó tạo một mục liên quan mới trong bảng sự kiện, bây giờ tôi có các khóa ngoại mà tôi cũng cần kiểm tra và cập nhật.

Cuối cùng, tôi đã học được rằng UUID có thể tránh được điều này, nhưng sau đó cơ sở dữ liệu của tôi đã trở nên khá lớn và tôi sợ việc triển khai UUID đầy đủ sẽ tạo ra vấn đề về hiệu năng. Vì vậy, thay vì sử dụng UUID đầy đủ, tôi bắt đầu sử dụng các khóa chữ và số 8 ký tự được tạo ngẫu nhiên làm ID và tôi để mã hiện tại của mình để xử lý xung đột. Ở đâu đó giữa các khóa 8 ký tự hiện tại của tôi và 36 ký tự của UUID phải có một điểm ngọt ngào để loại bỏ xung đột mà không cần phình to, nhưng vì tôi đã có mã giải quyết xung đột, nên không nên ưu tiên thử nghiệm điều đó .

Vấn đề tiếp theo là bảng lịch sử lớn hơn khoảng 10 lần so với toàn bộ cơ sở dữ liệu còn lại. Điều này làm cho việc lưu trữ trở nên đắt đỏ và bất kỳ bảo trì nào trên bảng lịch sử đều có thể gây đau đớn. Giữ toàn bộ bảng cho phép người dùng khôi phục mọi thay đổi trước đó, nhưng điều đó bắt đầu cảm thấy như quá mức cần thiết. Vì vậy, tôi đã thêm một thói quen vào quy trình đồng bộ hóa trong đó nếu mục lịch sử mà thiết bị được tải xuống lần cuối không còn tồn tại trong bảng lịch sử, thì máy chủ không cung cấp cho nó các mục lịch sử gần đây, mà thay vào đó cung cấp cho nó một tệp chứa tất cả dữ liệu cho tài khoản đó. Sau đó, tôi đã thêm một cronjob để xóa các mục lịch sử cũ hơn 90 ngày. Điều này có nghĩa là người dùng vẫn có thể khôi phục các thay đổi dưới 90 ngày và nếu họ đồng bộ hóa ít nhất một lần sau mỗi 90 ngày, các bản cập nhật sẽ được tăng dần như trước đây. Nhưng nếu họ chờ lâu hơn 90 ngày,

Sự thay đổi đó đã làm giảm gần 90% kích thước của bảng lịch sử, do đó, việc duy trì bảng lịch sử chỉ làm cho cơ sở dữ liệu lớn gấp đôi thay vì lớn gấp mười lần. Một lợi ích khác của hệ thống này là đồng bộ hóa vẫn có thể hoạt động mà không cần bảng lịch sử nếu cần - như nếu tôi cần thực hiện một số bảo trì tạm thời ngoại tuyến. Hoặc tôi có thể cung cấp các khoảng thời gian rollback khác nhau cho các tài khoản ở các mức giá khác nhau. Và nếu có hơn 90 ngày thay đổi để tải xuống, tệp hoàn chỉnh thường hiệu quả hơn định dạng gia tăng.

Nếu tôi đã bắt đầu lại từ hôm nay, tôi sẽ bỏ qua việc kiểm tra xung đột ID và chỉ nhắm đến độ dài khóa đủ để loại bỏ xung đột, với một số loại kiểm tra lỗi chỉ trong trường hợp. Nhưng bảng lịch sử và sự kết hợp của tải xuống gia tăng cho các bản cập nhật gần đây hoặc tải xuống đầy đủ khi cần đã hoạt động tốt.


1

Đối với đồng bộ hóa (thay đổi) delta, bạn có thể sử dụng mẫu pubsub để xuất bản các thay đổi trở lại cho tất cả các khách hàng đã đăng ký, các dịch vụ như trình đẩy có thể làm điều này.

Đối với nhân bản cơ sở dữ liệu, một số khung web sử dụng cơ sở dữ liệu nhỏ cục bộ để đồng bộ hóa cơ sở dữ liệu phía máy chủ thành cục bộ trong cơ sở dữ liệu trình duyệt, đồng bộ hóa một phần được hỗ trợ. Kiểm tra máy đo .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.