thảo luận Xin các bác chỉ giáo solution cho issue này

oshp1512

Junior Member
Hi các bác, em đang làm dự án mà có issue nho nhỏ chưa xử được, nhờ các bác cho em cao kiến xử lý với =((
Tiền đề:
Có 2 server A, B độc lập. DB độc lập. Nghiệp vụ là sync data 1 bảng (vd bảng Product) của 2 DB này
ở phía B sẽ có thêm 1 column is_update để đánh dấu row đó cần được sync
VD:
1713947979353.png


Xử lý hiện tại:
Ban đầu 2 bên A, B có row id 1 cần được sync data: column is_delete của item ở B đang false, và A cần sync nó
1713948027784.png


A sẽ chạy batch 5s/1 lần và xử lý theo flow như dưới
1. Đầu tiên call API sang B lấy ra những thằng cần sync, khi B được A request sang thì get những row có flag is_update True để reponse cho A -> B trả về cho A là data của id 1
2. Sau khi A nhận được, A sẽ dựa vào data đó để sync vào DB A.
1713948195555.png


3. Update db A xong, thì sẽ call api sang B, truyền data là id những thằng được A sync thành công -> truyền cho B id 1 để B update lại flag is_update False
1713948297466.png


-> Flow như vậy là xong, tới đây batch vẫn chạy nhưng không có flag is_update nào bật nữa thì sẽ không sync data

ISSUE:
Hiện tại ở step 2 việc sync data vào A vì một lý do nào đó ở phía server A mà fail (lost connect/full cpu load/....), thì step 3 vẫn tiếp diễn, dẫn đến A chưa sync thành công mà B vẫn update lại flag is_update sang FALSE -> không đồng bộ data

Câu hỏi:
Có cách nào để tạo dựng cơ chế có thể confirm được rằng xử lý đồng bộ đã hoàn thành dù cho ở bất cứ trạng thái như thế nào không?
 
3. Update db A xong, thì sẽ call api sang B, truyền data là id những thằng được A sync thành công -> truyền cho B id 1 để B update lại flag is_update False
View attachment 2458888

-> Flow như vậy là xong, tới đây batch vẫn chạy nhưng không có flag is_update nào bật nữa thì sẽ không sync data

ISSUE:
Hiện tại ở step 2 việc sync data vào A vì một lý do nào đó ở phía server A mà fail (lost connect/full cpu load/....), thì step 3 vẫn tiếp diễn, dẫn đến A chưa sync thành công mà B vẫn update lại flag is_update sang FALSE -> không đồng bộ data
Thím handle error phía A cho tốt là xong :boss:
 
dùng debezium đi bác (nếu không phải database oracle), nếu handle không thành công thì debezium nó sẽ chạy lại tới khi nào thành công nó mới continue, nếu chạy hoài không thành công thì nó dừng luôn, bạn vào sửa cho nó thành công xong mới đi tiếp
 
Đúng, bug được phát sinh do handle Êrror ở A. Cái này em fix rồi :D tuy nhiên ở phía câu hỏi là có cách nào để confimr được việc đồng bộ lỗi hay hoàn thành không í ạ
Cái này thím xài capture data change thôi, đại loại sẽ có thêm 1 column last_updated_at ở A và B, ở B check max last_updated <= max ở A thì là outdate, rồi cứ thế mà sync. Tuy nhiên thì việc đồng bộ thao tác xóa cứng data ở A và sync qua B thì sẽ phải chế thêm
 
Đúng, bug được phát sinh do handle Êrror ở A. Cái này em fix rồi :D tuy nhiên ở phía câu hỏi là có cách nào để confimr được việc đồng bộ lỗi hay hoàn thành không í ạ
Chưa hiểu lắm. Thì lúc handle error cứ throw ra record nào lỗi, hoặc lưu kết quả của batch process vô db là đc mà nhỉ
 
Chưa hiểu lắm. Thì lúc handle error cứ throw ra record nào lỗi, hoặc lưu kết quả của batch process vô db là đc mà nhỉ
Lúc trước handle error bị sai nên bug. Tuy nhiên e muốn hỏi có cách nào để confirm được việc đồng bộ data giữa 2 bên hay không thôi í ạ. Phía trên là e đang mô tả flow cho mn clear xử lý hiện tại thôi nè :)

via theNEXTvoz for iPhone
 
Lúc trước handle error bị sai nên bug. Tuy nhiên e muốn hỏi có cách nào để confirm được việc đồng bộ data giữa 2 bên hay không thôi í ạ. Phía trên là e đang mô tả flow cho mn clear xử lý hiện tại thôi nè :)

via theNEXTvoz for iPhone
xử lý sync giữa các platform kiểu này nên build service thứ 3 để orchestration nhé, các platform kia cung cấp các api để get/update record, còn sync flow để service thứ 3 kia xử lý
 
Lúc trước handle error bị sai nên bug. Tuy nhiên e muốn hỏi có cách nào để confirm được việc đồng bộ data giữa 2 bên hay không thôi í ạ. Phía trên là e đang mô tả flow cho mn clear xử lý hiện tại thôi nè :)

via theNEXTvoz for iPhone
mình nghĩ nếu có thể thì làm thêm 1 bảng database để track status + lock giữa các job khi scale thằng A, nếu database ở A chết nữa thì khi log xuống ứng dụng để có thể trace lại. :(
 
1. Bạn tạo 1 staging table ST bao gồm các dòng có is_update = FALSE của db B
2. Dùng table ST để tìm trong db A những dòng có cột is_update khác nhau (ST = FALSE, A = TRUE)
3. Filter is_update = TRUE trong table ST xong rồi count(id)
4. If count(id) > 0 do_update() then return count(id) else "data is up-to-date"
5. Drop table ST
 
Tốt nhất là nên gom về 1 chỗ và single source of truth. Còn câu chuyện đồng bộ thì bạn sẽ không thể nào sure 100% là luôn đồng bộ và không có lỗi được. Các cơ chế đồng thuận chỉ có giải pháp là phát hiện lỗi và sửa lỗi chứ sync up 1-1 như này thì khó, vì bạn không biết chắc được được là B hay A sẽ lỗi.

Tạm chữa cháy thì bạn có thể thêm 1 cột versioning. Khi có thay đổi ở row nào thì tăng version lên, check khác version thì update. Nhưng cách này chỉ có thể validate là có lỗi hay không thôi, bạn vẫn phải quyết định là nên trust bên nào.
 
Bác thử ngâm cứu two phase commit nếu vẫn muốn tách riêng, hoặc là cái table kia ở B thì cho về A luôn, write chỉ trên DB A thôi, xong dùng CDC qua B, sẽ ko thay đổi luồng read ở B
 
Có lý do gì bắt buộc không sao lại phải call qua lại vậy thím? Sao không phải là A call qua B để lấy data, nếu khác thì sync ko thì thôi
 
Call qua lại nhức đầu quá thím nên chia ra 1 thằng chỉ đọc, thằng còn lại có thể insert, update, delete,....

Ví dụ A cần bảng product của B đi.
Thì A chỉ cần thông tin trong bảng product đúng không? Vì nên chỉ có 1 source of truth, nên B có thể inser, update, delete thông tin trong bảng product. Vậy thì mỗi lần 1 row được update thì B có thể publish 1 event, bên A sẽ consum cái event này rồi insert/update/delete cho bảng product. Khỏi phải call qua lại làm gì hết :D

Cái này đảm bảo data bên B luôn luôn là mới nhất, sau đó A mới cập nhật theo, nếu A cập nhật fail thì thêm cơ chế retry,... bla bla
 
Call qua lại nhức đầu quá thím nên chia ra 1 thằng chỉ đọc, thằng còn lại có thể insert, update, delete,....

Ví dụ A cần bảng product của B đi.
Thì A chỉ cần thông tin trong bảng product đúng không? Vì nên chỉ có 1 source of truth, nên B có thể inser, update, delete thông tin trong bảng product. Vậy thì mỗi lần 1 row được update thì B có thể publish 1 event, bên A sẽ consum cái event này rồi insert/update/delete cho bảng product. Khỏi phải call qua lại làm gì hết :D

Cái này đảm bảo data bên B luôn luôn là mới nhất, sau đó A mới cập nhật theo, nếu A cập nhật fail thì thêm cơ chế retry,... bla bla
Vậy em giả sử có nhu cầu cập nhật bên A và em thể làm cái FE của A cập nhật thẳng vào B, đại loại vậy thì chắc mình phải chủ động sync qua về thím nhỉ?
 
Nghĩa là bài toán đồng bộ dữ liệu từ B sang A đúng không?
Cách Mô tả cứ bị ngược ngược.

Với những dạng bài này nếu dùng API để đồng bộ thì nên gọi từ B sang A chứ ngược lại như thế kia phải thêm 1 API

Thứ 2 nữa là với kiểu này dùng flag thôi là không đủ. Ví dụ case:
  • B updated, (giá trị v1)
  • A đọc dữ liệu B đọc cái vừa updated. (Đọc được v1)
  • B update lần nữa. (Giá trị v2)
  • A clear cái flag thành false.
=> Dữ liệu bên A sẽ sai (A là v1 còn bên B đã thành v2 rồi)
Cho đảo chiều gọi là B gọi A đồng bộ dữ liệu thì vẫn dính lỗi đó.

Cách giải quyết là dùng versioning, thêm một cột version nữa vào product.
Mỗi lần sửa product sẽ vừa set flag = true, vừa tăng version.

Còn khi A thực hiện clear flag trong bảng bên B bằng API thì cũng phải truyền thêm version, nếu version bằng thì mới cho phép clear (dạng optimistic locking)

Còn muốn trace error nữa thì có thể đẻ thêm một bảng log error actions.
Nếu có lỗi gì thì insert vào bảng đó.
Có thể thêm một cột nữa vào retry_count để giới hạn số lần retry.
Hoặc kiểu exponentially backoff.
Cách này phù hợp khi B gọi A để update hơn
 
Last edited:
Lĩnh hội nhiều ý kiến hay, đa tạ các thím ạ. :haha:
Tuy nhiên em vào chỉ để fix bug nên là nhiều solution không thể apply được. Logic code đã chạy như vậy rồi nên là các thắc mắc tại sao e cũng bó tay k giải thích đc nha :confuse:

via theNEXTvoz for iPhone
 
dùng debezium đi bác (nếu không phải database oracle), nếu handle không thành công thì debezium nó sẽ chạy lại tới khi nào thành công nó mới continue, nếu chạy hoài không thành công thì nó dừng luôn, bạn vào sửa cho nó thành công xong mới đi tiếp
Nếu thiết kế đúng thì làm theo cách này mới là đúng nhất này. Mở rộng ra thì solution sẽ là sử dụng các tool CDC (Change Data Capturing) mà debezium là 1 ứng cử viên. Các tool nó viết ra nó tính đến hết các trường hợp cho mình rồi.
 
um, debezium cũng dễ implement, thớt rảnh implement thử sẽ thấy nó đơn giản hơn các solution khác nhiều mà ko phải can thiệp gì ở tầng service hay logic code, kiểu nó auto luôn ấy
 
Cái này đơn giản mà nhỉ, bên A làm con thread quét 1 api hoặc db ở bên B xong đẩy vào queue nào đó, sau đó update luôn is_process =True ở bên B, còn thằng A nhận được transaction rồi thì phải tự xử lý false phải log lại
 
Back
Top