Chương 192
Tiếng quạt trần của văn phòng Tô Hiến Thành quay đều đều, hắt xuống những vệt nắng chiều xiên khoai qua rèm lá sách. Trên bảng trắng đặt ở góc phòng họp nhỏ, những nét bút lông màu xanh và đỏ đan chéo nhau thành một ma trận chằng chịt.
Minh đứng chống một tay lên cạnh bảng, tay kia xoay xoay cây bút lông. Những vệt mực đen bám trên đầu ngón tay cậu chưa kịp rửa.
“Luồng dữ liệu từ đối tác logistics bên Nhật trả về hiện tại đang chạy qua một con proxy trung gian ở Tokyo,” Minh gạch một đường đỏ đậm nối từ ô vuông ký hiệu ‘Narita/Osaka Cargo’ về một cụm có chữ ‘Aggregator’. “Vấn đề là, khi dữ liệu biên nhận thông quan được đồng bộ ngược về hệ thống đối soát của Cổng Việt, nó phải đi qua hàng đợi đồng bộ của NỢ SỔ. Hai cái này chung một database schema cũ. Nếu lượng đơn hàng Tết từ Tokyo tăng gấp ba theo tiến độ mà chị Linh báo, database sẽ bị nghẽn ở khâu ghi nhận lịch trình.”
Hoàng ngồi trên chiếc ghế xoay, hai tay đan vào nhau đặt trước cằm. Cậu nhìn sơ đồ.
Nếu là một năm trước, khi giao diện của Hệ thống Kiến Quốc còn nhấp nháy ở góc mắt, Hoàng sẽ không mất quá ba giây để đưa ra câu trả lời. Hệ thống sẽ hiển thị một tỷ lệ rủi ro cụ thể, kèm theo một Mảnh tương lai chỉ rõ cấu trúc tối ưu cho năm 2017. Hoàng chỉ việc đọc lại các chỉ số, gật đầu, và bảo Minh viết theo đúng sơ đồ định sẵn đó. Minh sẽ làm theo, dù trong lòng luôn có một vết gợn hoài nghi về việc tại sao Hoàng luôn chọn đúng phương án mà không cần qua các vòng thử nghiệm mệt mỏi.
Nhưng bây giờ, trước mắt Hoàng chỉ là một tấm bảng nhựa trắng loang lổ vết mực cũ và một người kỹ sư đang chờ cậu phản biện bằng logic thật sự. Không có thanh trạng thái, không có gợi ý ẩn, không có lưới an toàn nào bên dưới.
“Database dùng chung hiện tại là MySQL phải không?” Hoàng hỏi, giọng điệu chậm rãi.
“Đúng. Bản monolith cũ từ hồi anh viết,” Minh không ngại nhắc lại nguồn gốc của đống mã nguồn cũ. “Nó có quá nhiều ràng buộc khóa ngoại (foreign keys) giữa bảng dữ liệu tiệm tạp hóa và bảng hành trình hàng hóa của Cổng Việt. Khi quy trình cân đo của chú Tân dưới kho kích hoạt cập nhật trạng thái, nó khóa luôn cả bảng đối soát doanh thu của tiệm. Em muốn tách riêng hai database này ra.”
“Tách ra thì giải quyết được vấn đề khóa bảng (table locking),” Hoàng đứng dậy, bước đến bên bảng trắng, nhặt một cây bút lông màu xanh lá. “Nhưng Minh, cậu tính thế nào về tính nhất quán dữ liệu (data consistency)? Dữ liệu logistics đi qua nhiều chặng, từ nhà cung cấp miền Trung, lên xe Nam Hải, ra sân bay, rồi sang tới tay anh Tuệ ở Shin-Okubo. Nếu chúng ta tách database mà không có một cơ chế kiểm soát giao dịch phân tán (distributed transaction), một chặng bị mất mạng hoặc ghi lỗi thì làm sao đối soát được dòng tiền?”
Hoàng vẽ ba vòng tròn xanh lá độc lập đại diện cho ba chặng: Kho, Vận chuyển, và Pháp nhân Nhật.
“Nếu dùng cơ chế Saga pattern để quản lý giao dịch phân tán,” Minh lập tức phản biện, đầu bút lông đỏ của cậu gõ mạnh vào khoảng trống giữa ba vòng tròn. “Mỗi chặng hoàn thành sẽ phát ra một sự kiện (event). Nếu chặng sau lỗi, chúng ta chạy một sự kiện bù (compensating event) để rollback trạng thái của chặng trước. Như vậy không cần giữ kết nối database liên tục, cũng không sợ nghẽn mạng giữa hai đầu biên giới.”
“Chi phí phát triển hệ thống event-driven này mất bao lâu?” Hoàng quay sang nhìn Minh. “Chúng ta đang chạy đua với thời điểm đơn hàng Tết của chị Linh. Nếu viết Saga pattern từ đầu, cấu trúc mã nguồn sẽ phức tạp lên gấp ba. Team của cậu có gánh nổi không khi còn phải duy trì các cập nhật hàng ngày cho NỢ SỔ?”
Minh im lặng. Cậu không vội vàng cãi lại như hồi còn làm việc ở staging cũ. Cậu nhìn chăm chăm vào ba vòng tròn xanh lá Hoàng vừa vẽ, rồi tự tính toán trong đầu.
“Nếu chỉ dùng Saga cho những luồng có tính nhạy cảm cao như biên nhận ký gửi và dòng tiền,” Minh nói, giọng trầm xuống nhưng chắc chắn. “Còn các trạng thái vị trí địa lý của thùng hàng, chúng ta chấp nhận cập nhật bất đồng bộ (eventual consistency) qua một hàng đợi tin nhắn đơn giản. Như vậy giảm được 60% khối lượng công việc viết mã bù trạng thái.”
Hoàng gật đầu. Đó là một sự thỏa hiệp hợp lý giữa lý thuyết hệ thống sạch và áp lực thời gian của thực tế vận hành. “Tôi đồng ý hướng này. Nhưng cấu trúc này đòi hỏi khâu đối soát tài chính phải chạy rất chuẩn. Nếu tiền về tài khoản bên Nhật của anh Tuệ hoặc Hiếu mà dữ liệu hành trình chưa kịp đồng bộ về đây để cập nhật số dư cho nhà cung cấp miền Trung, chúng ta sẽ bị lệch sổ.”
Cửa phòng họp nhỏ bật mở nhẹ. Phương Anh bước vào, tay bưng một chiếc khay nhựa có ba ly nước ấm và một đĩa bánh quy nhỏ. Cô đặt khay xuống góc bàn, mắt nhìn lướt qua sơ đồ xanh đỏ trên bảng trắng.
“Dòng tiền sẽ không bị lệch nếu các bạn đưa khâu đối soát tài chính ra khỏi luồng xử lý thời gian thực của dữ liệu logistics,” Phương Anh nói, đứng khoanh tay bên cạnh Hoàng. Cô không biết nhiều về Saga hay database locking, nhưng cô biết cách dòng tiền di chuyển giữa các pháp nhân. “Hiện tại, tiền khách thanh toán bên Nhật được gom theo tuần qua tài khoản của anh Tuệ và Hiếu trước khi chuyển về Việt Nam. Về mặt pháp lý và tài chính, tôi không cần biết mỗi giây thùng hàng nằm ở đâu trên xe tải. Tôi chỉ cần hệ thống xuất ra được một bản đối chiếu tĩnh vào lúc 23 giờ 59 phút mỗi ngày, khớp giữa mã QR của thùng hàng đã thông quan và khoản tiền thực nhận trong tài khoản tạm giữ.”
Minh nhìn Phương Anh, rồi nhìn sang Hoàng.
“Đúng,” Hoàng gõ nhẹ đầu bút vào bảng. “Chúng ta không cần cố gắng đồng bộ tài chính theo thời gian thực (real-time). Chỉ cần chốt sổ cuối ngày (end-of-day reconciliation). Như vậy hệ thống dữ liệu của Minh sẽ bớt được một gánh nặng cực kỳ lớn. Các sự kiện tài chính chỉ cần ghi nhận dạng log tĩnh, cuối ngày chạy một job đối soát tự động.”
“Job đối soát đó sẽ do bộ phận tài chính chạy thủ công một lần để kiểm tra chéo trước khi hệ thống tự động ghi nhận số dư mới cho nhà cung cấp,” Phương Anh bổ sung thêm một ràng buộc thực tế. “Tôi cần một nút bấm trên dashboard để nhân viên kế toán xác nhận số liệu thực tế khớp với sao kê ngân hàng trước khi tiền được chuyển vào ví NỢ SỔ của tiểu thương. Không tự động hoàn toàn ở khâu này.”
Minh gật đầu, ghi chú nhanh vào cuốn sổ tay đặt trên bàn họp. “Em hiểu. Một lớp phê duyệt thủ công (manual approval step) trong quy trình tài chính. Cái này dễ làm, chỉ cần một trạng thái ‘Pending Reconciliation’ trên bảng đối soát.”
Hoàng nhìn Minh viết. Cậu cảm thấy một sự nhẹ nhõm kỳ lạ chạy dọc sống lưng.
Không còn những chỉ số ảo hiển thị tỷ lệ phần trăm thành công hay thất bại. Không còn cảm giác cô độc của một người phải gánh toàn bộ đáp án đúng trong đầu và tìm cách diễn sao cho giống một người bình thường. Hoàng đang đứng đây, tranh luận và lắng nghe những người giỏi nhất trong lĩnh vực của họ cùng nhau giải quyết một bài toán thật. Nếu hệ thống này có lỗi, đó là lỗi chung của cả team, và họ sẽ cùng ngồi lại ở chiếc bàn này để sửa nó.
“Chúng ta sẽ thử nghiệm thế nào?” Hoàng hỏi Minh.
“Em sẽ tạo một nhánh sandbox mới, chạy mô phỏng luồng dữ liệu của 100 đơn hàng cũ từ Tokyo về,” Minh gác cây bút lông lên khay dưới chân bảng trắng. Cậu lau hai bàn tay vào chiếc quần jean cũ, ánh mắt nhìn thẳng vào Hoàng. “Nếu sandbox chạy ổn định trong ba ngày, không có lỗi khóa bảng và dữ liệu đối soát khớp hoàn toàn với file Excel của Phương Anh, chúng ta mới cho merge vào production. Không vội vàng deploy trực tiếp nữa.”
Minh dừng lại một chút, nhìn đĩa bánh quy trên bàn rồi quay lại nhìn bảng trắng.
“Kiến trúc này là của chúng ta vẽ, không phải của anh hay của tôi. Nếu nó sập, chúng ta cùng sửa.”
Hoàng mỉm cười, cầm ly nước ấm lên. “Được. Cứ theo quy trình đó mà làm.”