You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XPages应用:并发保存时生成无重复用户编号的高性能方案咨询

Fixing Duplicate Sequence Numbers in XPages Without Killing Performance

Hey there! That duplicate sequence number issue during concurrent saves is a classic pain point in XPages apps—glad you're moving away from FTSearch and UpdateIndex, since those are total performance killers for this use case. Let's dive into some solid, efficient alternatives that'll keep your app snappy while guaranteeing unique, sequential IDs.

1. Database Counter Document with Locking

This is the most reliable and straightforward approach for sequential IDs. The idea is to use a single dedicated document in your database to track the current highest sequence number. When a user saves a new record, you lock this counter document, increment the value, assign it to your new document, then unlock and save the counter.

Example Java Code (XPages-friendly):

// Get the current database and counter document
Database db = ExtLibUtil.getCurrentDatabase();
Document counterDoc = db.getDocumentByKey("UserSequenceCounter", true);

// Initialize counter if it doesn't exist
if (counterDoc == null) {
    counterDoc = db.createDocument();
    counterDoc.replaceItemValue("Form", "Counter");
    counterDoc.replaceItemValue("CounterID", "UserSequenceCounter");
    counterDoc.replaceItemValue("CurrentMax", 0);
    counterDoc.save();
}

// Lock the counter to prevent concurrent writes
counterDoc.lock();
try {
    // Increment the sequence
    int currentVal = counterDoc.getItemValueInteger("CurrentMax");
    int newSequence = currentVal + 1;

    // Assign this new sequence to your user's document
    Document userDoc = db.createDocument();
    userDoc.replaceItemValue("Form", "User");
    userDoc.replaceItemValue("UserID", newSequence);
    // Add other user fields...
    userDoc.save();

    // Update the counter
    counterDoc.replaceItemValue("CurrentMax", newSequence);
    counterDoc.save();
} finally {
    // Always release the lock to avoid deadlocks
    counterDoc.unlock();
}

Why this works:

  • The lock() method ensures only one user can modify the counter at a time, eliminating duplicates.
  • This uses basic document read/write operations—no full-text indexing or expensive searches, so performance stays fast even with many concurrent users.
  • It’s persistent across server restarts, so you won’t lose track of the sequence.

2. UUIDs for Non-Sequential Unique IDs

If you don’t strictly need sequential numbers (just unique, user-specific identifiers), skip the sequence entirely and use UUIDs. These are guaranteed to be unique across time and space, with zero concurrency issues.

Example Code:

// Generate a UUID string
String uniqueUserID = java.util.UUID.randomUUID().toString();

// Assign to your user document
Document userDoc = db.createDocument();
userDoc.replaceItemValue("Form", "User");
userDoc.replaceItemValue("UserID", uniqueUserID);
userDoc.save();

Why this works:

  • No database locks, no counter documents—just a quick in-memory generation.
  • Perfect if the ID doesn’t need to be human-readable or sequential (like internal system IDs).
  • Zero performance overhead, even under heavy load.

3. Cached Counter with Database Sync (For High Concurrency)

If you’re dealing with extremely high traffic (hundreds of concurrent saves), you can optimize the counter approach by caching the current sequence value in memory to reduce database hits. Just make sure to sync the cached value back to the counter document periodically (or on server shutdown) to avoid data loss.

Quick Overview:

  • Use a static AtomicInteger in a Java bean to track the current sequence in memory.
  • When the app starts, load the initial value from the counter document.
  • For each new ID, increment the AtomicInteger (thread-safe) and assign it.
  • Sync the cached value to the database every X minutes, or after X increments, to keep it persistent.

This cuts down on database write operations, making it even faster for high-load scenarios.

Why FTSearch/UpdateIndex Was a Bad Fit

Just to confirm your hunch: FTSearch relies on the database’s full-text index, which is slow to query for real-time sequence checks. Calling UpdateIndex forces the server to rebuild the index immediately, which eats up CPU and disk I/O—terrible for performance when multiple users are saving at once. The above methods avoid all that overhead.

Pick the approach that fits your ID requirements: sequential vs. non-sequential, and adjust based on your app’s traffic volume. All of these will keep your XPages app running smoothly without duplicate IDs.

内容的提问来源于stack exchange,提问作者Felipe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:51:01