_id tự tăng trong mongodb
Không như những Hệ quản trị CSDL khác như MySQL, PostgreSQL,… MongoDB không có khái niệm Auto-Increment. Mỗi một bản ghi khi được thêm vào CSDL sẽ có 1 object ID với các ký tự ngẫu nhiên (Hoặc theo 1 quy tắc do MongoDB định nghĩa) Show Bài viết này sẽ hướng dẫn cách tạo một trường tự động tăng (Auto-Increment Field) trong MongoDB Sử dụng counters collectionÝ nghĩa của cách này là tạo 1 bảng để lưu lại giá trị tăng dần của ID. Ví dụ: Tạo bảng users có trường _id là số tư nhiên tự tăng Mở Mongo Shell để thực hiện các bước sau: Bước 1: Tạo bảng counters bằng việc thêm 1 bản ghi có cấu trúc object như sau: db.counters.insert( { _id: "userid", seq: 0 } ) Bước 2: Tạo hàm javascript để lấy ID tiếp theo (Cú paste function này vào Mongo Shell) function getNextSequence(name) { var ret = db.counters.findAndModify( { query: { _id: name }, update: { $inc: { seq: 1 } }, new: true } ); return ret.seq; } Bước 3: Xác nhận bằng việc thêm dữ liệu cho bảng users như sau db.users.insert( { _id: getNextSequence("userid"), name: "Nguyen Van A" } ) db.users.insert( { _id: getNextSequence("userid"), name: "Nguyen Van B" } ) Kết quả: Chú ý: Để tạo thêm trường Auto-Increment cho bảng khác ví dụ bảng products chẳng hạn. Chúng ta thêm 1 bản ghi vào bảng counters với trường _id: “productid”, rồi thêm dữ liệu cho bảng products giống như là: db.products.insert( { _id: getNextSequence("productid"), name: "Máy hàn" } ) Lưu ý: MongoDB khuyên chúng ta nếu không cần thiết thì không nên tạo auto-increment.
Nguồn: vinasupport.com Mình đang code 1 website cá nhân, không đăng kí doanh nghiệp nên xài API chùa của bank để check lịch sử giao dịch rồi cộng tiền. Ý tưởng là khách sẽ chuyển tiền vào bank mình theo cú pháp kiểu như:
Nhìn thôi cũng biết mình chọn cách nào rồi đúng không, email thì quá dài và 1 số bank không cho nhập kí tự đặc biệt, id mongodb thì đúng là thảm hoạ cho người dùng, username và số là ok nhất rồi. Tuy nhiên collection bên mình không có field Dưới đây là bản phác thảo mình viết để hệ thống lại. Bài toán trên của mình thì mình xài cách 1 dưới đây do số lượng User đăng kí đồng thời khá thấp và mức delay chấp nhận được. Các cách khác sau mình khi cần scale mình sẽ dùng tới nên code có thể chưa được clean nhé! Atomic UpdateĐúng như cái tên của của nó, findOneAndUpdate là giải pháp đầu tiên mà bất kì coder nào cũng nghĩ tới. Tạo 1 collection
Cơ mà với bài toán của mình, mình sẽ thêm 1 đoạn code nữa để khi thanh toán, nếu user không có Thực ra cũng có 1 cách nữa mình nghĩ tới đó là vứt luôn cái đống auto-inc unique mongodb này vào sọt rác, khi người dùng thanh toán thì mới bắt họ update username nếu chưa có là xong, nhưng thôi, thử thách bản thân 1 tí xem sao.
Bây giờ web bạn đủ lớn thì cái giải pháp này chính là thứ bopdai web của bạn. Ví dụ giờ có 200 cái request đăng kí (hoặc user nạp lần đầu nếu bạn theo phương pháp của mình) post lên server 1 phát thì sao. Đúng rồi, cả 200 request này sẽ bị block mới lệnh atomic udpate findOneAndUpdate của bộ đếm. Vẫn là Atomic Update nhưng trên multiple documentÝ tưởng đơn giản lắm, thay vì atomic trên 1 cái document thì giờ atomic trên nhiều cái thôi, ez game Ví dụ mình tạo 10 bộ đếm là 10 doc, mỗi 1 doc đại diện cho 1 khoảng số, ví dụ từ Khởi tạo bộ đếm
Chỗ dùng bộ đếm bây giờ sẽ đổi thành
Dễ, thì reset bộ đếm qua 1 bộ đếm khác
Ví dụ
Vẫn là Atomic Update trên multiple document nhưng thêm queueChỗ này ngắn ngọn dễ hiểu đối với ai đã biết cách dùng Queue (nếu chưa biết thì bạn có thể tham khảo qua các bài viết của anh @monmen nhé). Thay vì random thì đẩy nó vào queue, và tạo số lượng worker = bộ đếm mà bạn có, để phân bổ đều trên các bộ đếm. Chỗ reset bộ đếm khi full dễ dàng hơn (vì không cần lo nhiều request đồng thời cùng gọi đến 1 bộ đếm đã full).
Random số ngẫu nhiên rồi kiểm tra xem đã tồn tại trong DB chưaMột trong các cách mình nghĩ tới, Tuy nhiên chỉ phát huy tác dụng khi mà có dải số rộng, không phù hợp với bài toán của mình cho lắm. Chuyển Atomic qua cho Redis và update vào DBCách này cũng khá đơn giản, thay vì mỗi 1 lần call couter mình lại gọi tới db dẫn tới thắt cổ chai, xử lí 1 lệnh trên db như vậy mất dỡ 40ms, nghĩa là 1 giây chỉ xử lí đc vài chục request. Thay vào đó mình sẽ chuyển bài toán tăng atomic qua cho redis nắm giữ và chỉ update vào database mỗi 10s. Code chay thì đơn giản, tuy nhiên phải catch được lỗi và retry hoặc pause các queue có xử dụng tới router khi app mới khởi động, xử lí được việc chậm delay update từ reds vào mongodb, listen event redis tắt save vào db. Good luck ae! Bài viết tới đây là hết rồi. Có lỗi lầm hay thiếu sót gì các bạn cứ góp ý nhiệt tình nhé. |