Telegram getUpdates offset: tránh xử lý trùng và mất cập nhật
Telegram coi một cập nhật là đã được xác nhận khi bạn gọi getUpdates với offset lớn hơn update_id của cập nhật đó. Chỉ nhận được phản hồi chưa phải là xác nhận. Để tránh mất việc, hãy lưu bền vững các cập nhật trước khi gửi yêu cầu tiếp theo với offset lớn hơn. Đồng thời lưu offset tiếp theo cùng dữ liệu để chịu được việc khởi động lại, và tách chống trùng khỏi xử lý nghiệp vụ.
Điểm chính
offsetlà ranh giới xác nhận, không phải số trang hay số lượng tin nhắn.- Chỉ tiến checkpoint khi mọi cập nhật sắp được xác nhận đã được lưu an toàn.
- Mỗi bot chỉ nên có một tiến trình polling đang giữ quyền nhận; mở rộng các worker phía sau thay vì thêm poller.
- Hộp nhận bền vững bảo vệ khâu tiếp nhận, nhưng thao tác với hệ thống ngoài vẫn cần chiến lược thử lại riêng.
Bài viết giả định bạn đã chọn polling. Nếu webhook vẫn được cấu hình, hãy xem quy trình chuyển giữa getUpdates và setWebhook trước. Phạm vi ở đây là những gì cần commit giữa hai lần polling thành công, không phải chọn lại phương thức nhận dữ liệu.
Offset của getUpdates thực sự xác nhận điều gì?
Tài liệu Telegram Bot API chính thức định nghĩa offset là mã định danh của cập nhật đầu tiên cần trả về. Nếu bỏ qua tham số này, Telegram trả về từ cập nhật chưa xác nhận cũ nhất. Lần gọi tiếp theo với offset lớn hơn mã của một cập nhật sẽ xác nhận cập nhật đó.
Ví dụ giả định: phản hồi chứa 8100, 8101 và 8102. Gọi tiếp với offset=8103 sẽ xác nhận cả ba, ngay cả khi ứng dụng mới xử lý xong cập nhật cuối cùng. Telegram không kiểm tra cơ sở dữ liệu của bạn hay đợi CRM hoàn tất.
| Cách làm tắt | Rủi ro | Thiết kế an toàn hơn |
|---|---|---|
| Lưu ID lớn nhất trước khi lưu cả lô | Sau khi khởi động lại có thể bỏ qua cập nhật chưa từng được lưu | Commit hộp nhận và offset tiếp theo cùng nhau |
| Tiến offset khi tác vụ song song nhanh nhất hoàn tất | Các cập nhật trước đó còn dang dở cũng có thể bị xác nhận | Dựa vào tiến độ lưu bền vững, không dựa vào thứ tự worker hoàn tất |
| Chỉ giữ offset trong bộ nhớ | Mất checkpoint cục bộ khi khởi động lại | Đọc checkpoint bền vững riêng cho từng bot |
| Dùng offset âm để sửa lỗi trùng | Các cập nhật trước đó trong hàng đợi bị bỏ | Kiểm tra quyền polling và cơ chế chống trùng |
Telegram nêu rõ offset âm lấy cập nhật từ cuối hàng đợi và quên các cập nhật trước đó. Đây không phải cách khôi phục dữ liệu production vẫn còn cần xử lý.
Tách tiến độ tiếp nhận khỏi trạng thái hoàn tất nghiệp vụ
Một thiết kế thực tế có hai loại bản ghi do ứng dụng quản lý: hộp nhận chứa toàn bộ cập nhật và checkpoint chứa offset tiếp theo. Đây là khái niệm lưu trữ nội bộ, không phải trường mới của Telegram API.
Dùng định danh ổn định của bot kết hợp với update_id làm khóa duy nhất cho hộp nhận. Không dùng chính bot token làm khóa cơ sở dữ liệu hoặc ghi nó vào log. Lưu mọi loại cập nhật được trả về, kể cả loại mà worker hiện tại chưa hiểu; có thể phân loại sau khi tiếp nhận.
Trình tự transaction được đề xuất:
Đọc offset tiếp theo đã lưu của bot này.
Gọi getUpdates bằng offset đó.
Nếu lô trả về rỗng, giữ nguyên checkpoint.
Nếu không, bắt đầu transaction cơ sở dữ liệu:
Chèn từng cập nhật; không chèn lại khóa duy nhất đã tồn tại.
Lưu max(update_id trong lô) + 1 làm offset tiếp theo.
Commit.
Chỉ thực hiện lần polling tiếp theo sau khi commit thành công.
Dùng worker riêng để xử lý các cập nhật đã lưu.
Đây là mã giả thiết kế, không phải một polling client hoàn chỉnh. Nó giả định có một chủ thể polling đang hoạt động, kho lưu trữ bền vững hỗ trợ transaction và ràng buộc duy nhất. Nếu transaction lỗi, dừng việc tiến offset và thử lại từ checkpoint đã lưu; không bắt lỗi lưu trữ rồi tiếp tục với offset lớn hơn.
Nếu hộp nhận và checkpoint nằm ở hai hệ thống khác nhau, tính nguyên tử trên không tự xuất hiện. Cần thiết kế việc bàn giao bền vững và đối soát, thay vì coi hai lần ghi thành công là một transaction.
Kiểm tra các ranh giới xảy ra sự cố
Các tình huống dưới đây là đề xuất kiểm thử nghiệm thu, không phải kết quả đo thực tế:
| Thời điểm dừng | Hành vi khôi phục mong đợi |
|---|---|
| Sau khi nhận lô, trước commit | Đọc checkpoint cũ; chấp nhận khả năng nhận lại dữ liệu |
| Trong transaction | Sau rollback không còn checkpoint chỉ cập nhật một phần |
| Sau commit, trước polling tiếp theo | Đọc checkpoint mới; công việc đã lưu vẫn sẵn sàng xử lý |
| Sau thao tác bên ngoài, trước khi ghi hoàn tất | Đối soát hoặc dùng tính idempotent của hệ thống đích; khóa tiếp nhận không đủ để ngăn thao tác lặp |
Cập nhật trùng phải được ánh xạ tới bản ghi hộp nhận hiện có. Nhưng bản ghi tồn tại không có nghĩa nghiệp vụ đã hoàn tất: worker vẫn phải tìm và thử lại công việc đã lưu nhưng chưa xong. Ngược lại, nhận lại cập nhật không nên tự động gửi thêm câu trả lời hay sửa CRM lần nữa.
Khi triển khai, hãy bàn giao quyền polling rõ ràng. Tiến trình phát triển bị quên chưa tắt, hoặc yêu cầu chẩn đoán thủ công với offset cao hơn, có thể xác nhận cập nhật ngoài đường lưu trữ của bạn. Đừng để thao tác tưởng là “chỉ đọc” thay đổi tiến độ production.
Giới hạn và ranh giới với UnifyPort
Telegram quy định cập nhật đầu vào không được giữ quá 24 giờ. Checkpoint không tạo ra kho lưu trữ vô thời hạn, và giảm offset không thể lấy lại cập nhật đã xác nhận hoặc hết hạn. Hãy kiểm tra khoảng gián đoạn như một khoảng có khả năng mất dữ liệu.
Nếu cần nhận từ tài khoản hiện có hoặc hợp nhất Telegram với Zalo và WhatsApp, hãy đọc so sánh Telegram Bot API webhook với webhook đầu vào hợp nhất. Giao diện không chính thức của UnifyPort dùng các sự kiện chuẩn hóa như message.received, không dùng offset polling của bot.
Tài liệu phân phối UnifyPort định nghĩa cơ chế xác nhận riêng. Cấu hình signing_secret, kiểm tra X-Device-Signature bằng HMAC-SHA256 trên dấu thời gian, một dấu chấm và các byte thô của yêu cầu. Sau đó lưu bền vững sự kiện trước khi trả phản hồi thành công. Các lần gửi lại sự kiện thông thường dùng lại X-Device-Event-Id. UnifyPort không có REST API đọc lịch sử tin nhắn và không bảo đảm phát lại payload bị bỏ lỡ. Đây không phải dịch vụ phục hồi cập nhật Bot API đã được xác nhận.
Câu hỏi thường gặp
Vì sao getUpdates cứ trả về cùng một cập nhật?
Kiểm tra xem yêu cầu tiếp theo có thực sự dùng offset lớn hơn các update_id đó không, và sau khi khởi động lại có đọc checkpoint đã lưu không. Hãy chống trùng an toàn thay vì xóa hàng đợi.
Có phải đợi tác vụ AI hoặc CRM hoàn tất mới được tiến offset?
Không cần nếu đã lưu bền vững toàn bộ cập nhật và có thể thử lại tác vụ độc lập. Chỉ giữ trong bộ nhớ chưa phải bàn giao bền vững.
Cách này có bảo đảm chỉ gửi câu trả lời đúng một lần không?
Không. Lưu nguyên tử ngăn một nhóm lỗi mất dữ liệu, nhưng lệnh gửi có thể thành công trước khi worker ghi nhận hoàn tất. Ranh giới đó cũng cần tính idempotent hoặc đối soát.
Bước tiếp theo và nguồn
Rà soát vòng lặp polling tại ranh giới commit cơ sở dữ liệu. Nếu triển khai bộ nhận cho tài khoản nhắn tin đã kết nối, hãy tuân theo cơ chế phân phối webhook, không áp dụng logic offset của Bot API.
- Telegram Bot API: getUpdates và Getting updates, kiểm tra ngày 2026-09-19.
- UnifyPort: phân phối webhook và xác minh chữ ký.
Biến tích hợp nhắn tin thành một pipeline sản phẩm ổn định.
Bắt đầu bằng cách gửi qua một API, rồi đưa mọi tin nhắn inbound trở lại hệ thống kinh doanh bằng sự kiện chuẩn.