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

如何实现单账号仅能登录一个共享数据库的Java游戏服务器?

限制单账号仅登录一台Java游戏服务器的方案

方案1:数据库新增在线状态标记

  • 在用户账号表(比如user_account)里加两个字段:is_online(布尔值,标记是否在线)、server_id(记录当前登录的服务器标识)
  • 登录逻辑改造成:
    1. 用户登录时先查数据库,看该账号is_online是不是true
    2. 要是已经在线,直接返回“账号已在其他服务器登录”
    3. 不在线的话,把is_online设为true,server_id填当前服务器ID,再完成登录流程
  • 异常情况处理:
    • 用户主动登出时,把is_online改回false,清空server_id
    • 加心跳检测:服务器每隔一段时间(比如30秒)检查客户端心跳,超过阈值没收到就重置该账号的在线状态
    • 服务器启动时,批量把对应server_id的账号在线状态重置,防止服务器宕机后状态残留

方案2:用行级锁避免并发登录竞态

  • 针对同一账号的登录请求,用数据库行级锁确保同一时间只有一个请求能处理,防止两台服务器同时处理同一账号登录导致状态混乱
  • Java代码示例:
// 登录时先获取账号行的排他锁,避免并发操作
String lockSql = "SELECT * FROM user_account WHERE username = ? FOR UPDATE";
try (Connection conn = getDbConnection()) {
    PreparedStatement lockStmt = conn.prepareStatement(lockSql);
    lockStmt.setString(1, loginUsername);
    ResultSet rs = lockStmt.executeQuery();
    
    if (rs.next()) {
        if (rs.getBoolean("is_online")) {
            throw new RuntimeException("账号已在其他服务器登录");
        }
        // 更新在线状态
        String updateSql = "UPDATE user_account SET is_online = true, server_id = ? WHERE username = ?";
        PreparedStatement updateStmt = conn.prepareStatement(updateSql);
        updateStmt.setString(1, currentServerId);
        updateStmt.setString(2, loginUsername);
        updateStmt.executeUpdate();
    }
} catch (SQLException e) {
    // 处理数据库异常
    e.printStackTrace();
}

方案3:会话集中管理(适合多服务器扩展)

  • 搭一个简单的会话管理中心,所有服务器的登录请求都先过这个中心验证
  • 中心维护一个在线账号映射表,记录每个账号当前登录的服务器ID
  • 登录时中心查映射表,已存在就拒绝登录;登出或异常断开时,中心移除对应记录
  • 这种方式后续加新服务器时不用改每个服务器的逻辑,统一在中心管理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 07:48:45