• 欢迎加入MineBBS QQ讨论群:点击查看所有的官方讨论群
  • 我们将于近期对服务器进行迁移,服务可能中断至多2日。请各位安排好自己的访问计划,造成不便敬请谅解!
  • MineBBS入站考试已经上线!想要成为【正式会员】解锁更多功能吗?快来参与吧!【点我去看】

已解决 我该如何更流畅的从数据库获取数据?

JiuRanX

【Lv:2】

正式会员
注册
2025/01/11
消息
6
金粒
286.00金粒
本服务器运行这经过修改的Spigot1.8.8核心,并且在CraftPlayer中添加了getPrefix、getSuffix、getGroup方法以便我们的开发者更容易的开发。
但是如果在一个子服务器中,服务器中人较多(大于10人),此时进入服务器就会卡顿,然后才会好,卡顿时长与当前服务器内玩家人数成正比例关系。
我们使用了HikariCP作为连接池。
以下是获取Prefix代码,其他与其类似:

Java:
@Override
    public String getPrefix() {
        try (Connection connection = Bukkit.getSugar().getLemonPermsDatabase().getDataSource().getConnection();
             Statement statement = connection.createStatement()) {
            ResultSet rs = statement.executeQuery("SELECT * FROM player_data WHERE uuid = '" + getUniqueId() + "'");
            if (rs.next()) {
                if (rs.getString("prefix") != null) {
                    return rs.getString("prefix");
                } else {
                    return getGroup().getPrefix();
                }
            } else {
                statement.executeUpdate("INSERT INTO player_data (uuid, name, group_name) VALUES ('" + getUniqueId() + "', '" + getName() + "', '默认')");
                return getGroup().getPrefix();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return new Group("默认").getPrefix();
    }

一下是对连接池的配置:
Java:
public Database(String url, int port, String db, String username, String password){
  HikariConfig APIConfig = new HikariConfig();
        APIConfig.setJdbcUrl("jdbc:mysql://" + url + ":" + port + "/" + db);
        APIConfig.setUsername(username);
        APIConfig.setPassword(password);
        APIConfig.addDataSourceProperty("verifyServerCertificate", String.valueOf(false));
        APIConfig.addDataSourceProperty("characterEncoding", "utf8");
        APIConfig.addDataSourceProperty("encoding", "UTF-8");
        APIConfig.addDataSourceProperty("useUnicode", "true");
        APIConfig.addDataSourceProperty("rewriteBatchedStatements", "true");
        APIConfig.addDataSourceProperty("jdbcCompliantTruncation", "false");
        APIConfig.addDataSourceProperty("cachePrepStmts", "true");
        APIConfig.addDataSourceProperty("prepStmtCacheSize", "275");
        APIConfig.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        APIConfig.addDataSourceProperty("socketTimeout", String.valueOf(TimeUnit.SECONDS.toMillis(30)));
        APIConfig.setMaximumPoolSize(50);
        dataSource = new HikariDataSource(APIConfig);
}


除了通过异步获取还有更好的解决方案吗?
 
解决方案
嗯,我们试验过了,确实奏效,但是由于异步,在玩家刚刚加入服务器调用方法时会直接返回默认值,所以我们团队的人必须把一些代码修改,而且大部分人都不愿意这么做:(还有其他更好的方法吗
使用 AsyncPlayerPreLoginEvent

补充:优先级为 MONITOR,并且判断满足 event.getLoginResult() == Result.ALLOWED 时才执行。这个事件本身就是异步执行,不需要再 runTaskAsynchronously
增加缓存机制。

将从数据库拿取到的数据存到 Map,写入数据库的时候也存到 Map,然后通过 BungeeCord 消息等方式通知其它服务器更新缓存。
如果这些数据是玩家相关,并且离线了数据就可以不要了,也可以在玩家上线或下线时清除缓存。

尽可能不要在事件中调用数据库(比如 PlayerJoinEvent),如果确实需要调用,请异步执行(Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { /*do sth*/ });

具体如何实现缓存可以参考我的插件:https://github.com/MrXiaoM/SweetAda...weet/adaptiveshop/database/OrderDatabase.java
 
增加缓存机制。

将从数据库拿取到的数据存到 Map,写入数据库的时候也存到 Map,然后通过 BungeeCord 消息等方式通知其它服务器更新缓存。
如果这些数据是玩家相关,并且离线了数据就可以不要了,也可以在玩家上线或下线时清除缓存。

尽可能不要在事件中调用数据库(比如 PlayerJoinEvent),如果确实需要调用,请异步执行(Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { /*do sth*/ });
嗯,我们试验过了,确实奏效,但是由于异步,在玩家刚刚加入服务器调用方法时会直接返回默认值,所以我们团队的人必须把一些代码修改,而且大部分人都不愿意这么做:(还有其他更好的方法吗
 
嗯,我们试验过了,确实奏效,但是由于异步,在玩家刚刚加入服务器调用方法时会直接返回默认值,所以我们团队的人必须把一些代码修改,而且大部分人都不愿意这么做:(还有其他更好的方法吗
使用 AsyncPlayerPreLoginEvent

补充:优先级为 MONITOR,并且判断满足 event.getLoginResult() == Result.ALLOWED 时才执行。这个事件本身就是异步执行,不需要再 runTaskAsynchronously
 
解决方案
使用 AsyncPlayerPreLoginEvent

补充:优先级为 MONITOR,并且判断满足 event.getLoginResult() == Result.ALLOWED 时才执行。这个事件本身就是异步执行,不需要再 runTaskAsynchronously
感谢
 

在线会员

  • greapeeeeeee
  • 天穹
  • 林壕
  • 2904435839
  • wwwjh
  • wldck
  • 九霄云境
  • 邪神龙哥
  • Mulali
  • Allen_Linong
  • banwang
  • baozi404404
  • 3598524526
  • adlahgerunce224
  • 235697
  • 真是432334
  • WZJWW1345
  • Happyday
  • Fyxcelyhh
  • UMK361433
...和 8 更多。
后退
顶部 底部