Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java和mysql高并发瓶颈解决方案_Java_Mysql - Fatal编程技术网

Java和mysql高并发瓶颈解决方案

Java和mysql高并发瓶颈解决方案,java,mysql,Java,Mysql,我们正在开发一个车辆跟踪系统,其中几个GPS设备使用Tcp连接不断将其GPS位置发送到服务器。Tcp communicator解码GPS位置并将数据插入数据库,在插入之前,我们进行一些选择和更新,但我使用准备好的语句来完成。现在,TCP communicator的一个线程提供一个设备请求。创建线程后,我们立即从池中获得一个连接。解码GPS数据后,我们对每个数据执行多重选择、更新和插入。随着设备数量的增加,到Mysql数据库的并发连接数量也在增加。我们现在预计每分钟会有3万到5万台设备输出数据。下

我们正在开发一个车辆跟踪系统,其中几个GPS设备使用Tcp连接不断将其GPS位置发送到服务器。Tcp communicator解码GPS位置并将数据插入数据库,在插入之前,我们进行一些选择和更新,但我使用准备好的语句来完成。现在,TCP communicator的一个线程提供一个设备请求。创建线程后,我们立即从池中获得一个连接。解码GPS数据后,我们对每个数据执行多重选择、更新和插入。随着设备数量的增加,到Mysql数据库的并发连接数量也在增加。我们现在预计每分钟会有3万到5万台设备输出数据。下面是整个tcp通信器的片段。我知道最终我们将面临向数据库中插入瓶颈。克服这种情况的最佳解决方案是什么?Java也能处理这么多并发性吗

public class comm8888 {
    HikariDataSource connectionPool = null;
    private Socket receivedSocketConn1;
    ConnectionHandler(Socket receivedSocketConn1) {
      this.receivedSocketConn1=receivedSocketConn1;
    }
    Connection dbconn = null;
    public void run() { // etc
     DataOutputStream w = null;
     DataInputStream r = null;  
     String message="";
     receivedSocketConn1.setSoTimeout(60000);
       dbconn = connectionPool.getConnection();
     dbconn.setAutoCommit(false);
     try {
         w = new DataOutputStream(new BufferedOutputStream(receivedSocketConn1.getOutputStream()));
         r = new DataInputStream(new BufferedInputStream(receivedSocketConn1.getInputStream()));
         while ((m=r.read()) != -1){
             //multiple prepared based sql select,update and insert here.
         }
     }
     finally{
        try {
            if ( dbconn != null ) {
              dbconn.close();
            }
        }
        catch(SQLException ex){
             ex.printStackTrace();
        }
        try{
           if ( w != null ){
                w.close();
                r.close();
                receivedSocketConn1.close();
            }
        }
        catch(IOException ex){
           ex.printStackTrace(System.out);
        }
      }
   }
}


    public static void main(String[] args) {
      new comm8888();
    }
    comm8888() {
      try {

          HikariConfig config = new HikariConfig();
                config.setJdbcUrl("jdbc:mysql://localhost:3306/testdata"); 
                config.setUsername("****"); 
                config.setPassword("****");      
                config.setMaximumPoolSize(20);      
          connectionPool = new HikariDataSource(config); // setup the connection pool           
       }
          catch (Exception e) {
                e.printStackTrace(System.out);
         }
          try 
          {
                   final ServerSocket serverSocketConn = new ServerSocket(8888);                
                   while (true){
                            try {
                                    Socket socketConn1 = serverSocketConn.accept();
                                    new Thread(new ConnectionHandler(socketConn1)).start();                     
                            }
                            catch(Exception e){
                                e.printStackTrace(System.out);
                            }
                        }
          } 
          catch (Exception e) {
             e.printStackTrace(System.out);

          }

    }
} 

一个问题是,如果设备数量增加,每个设备都会尝试连接不可扩展的db。 一种方法是异步地逐批处理。将所有消息存储在队列中,直到其达到批大小,然后作为批插入。它将保存网络,因为您没有逐个插入记录

如果您需要进一步的可扩展解决方案,那么可以使用nosql解决方案或主复制多节点拓扑来支持大流量和可用性


对于选择和更新,您可以使用需要根据您的用例进行分析的合并查询。如果存在合并查询,则会进行更新;如果不存在合并查询,则会进行插入。

一个问题是,如果设备数量增加,每个设备都会尝试连接不可扩展的数据库。 一种方法是异步地逐批处理。将所有消息存储在队列中,直到其达到批大小,然后作为批插入。它将保存网络,因为您没有逐个插入记录

如果您需要进一步的可扩展解决方案,那么可以使用nosql解决方案或主复制多节点拓扑来支持大流量和可用性


对于选择和更新,您可以使用需要根据您的用例进行分析的合并查询。合并查询将在存在时进行更新,如果不存在则进行插入。

将注释移到此处以进一步解释

dbconn = connectionPool.getConnection();
...
while (...) {
   // dbconn is held for up to 60 seconds which is not scalable
} 
因此,当实际上需要做一些事情来避免长时间的db连接时,您可以只获得一个dbConn

while (...) {
    // got some more data to process - now get a dbConn 
    dbconn = connectionPool.getConnection();
    // do inserts, etc.
    // commit and release the connection!
} 
另一种方法是通过发布到队列或调用REST服务来完全卸载与数据库的交互

while (...) {
    // got some more data to process
    // publish the data to a JMS queue
    // or post the data to a REST endpoint
    // there is no database interaction here at all!
} 

然后,消息使用者或REST端点处理数据并插入/更新数据库。这些消息/请求中的每一条都很小,因此数据库连接只能从池借用几毫秒(最多)。处理JMS消息/POST请求的服务器集群可以独立于最初接收原始套接字数据的服务器进行扩展。

将注释移到此处进行详细解释

dbconn = connectionPool.getConnection();
...
while (...) {
   // dbconn is held for up to 60 seconds which is not scalable
} 
因此,当实际上需要做一些事情来避免长时间的db连接时,您可以只获得一个dbConn

while (...) {
    // got some more data to process - now get a dbConn 
    dbconn = connectionPool.getConnection();
    // do inserts, etc.
    // commit and release the connection!
} 
另一种方法是通过发布到队列或调用REST服务来完全卸载与数据库的交互

while (...) {
    // got some more data to process
    // publish the data to a JMS queue
    // or post the data to a REST endpoint
    // there is no database interaction here at all!
} 

然后,消息使用者或REST端点处理数据并插入/更新数据库。这些消息/请求中的每一条都很小,因此数据库连接只能从池借用几毫秒(最多)。处理JMS消息/POST请求的服务器集群可以独立于最初接收原始套接字数据的服务器进行扩展。

我同意,并且我知道每个设备都会尝试连接到db。我正在考虑排队,但我仍然需要进行选择和更新,因此我仍然需要数据库连接。是否可以为多个连接运行选择和更新,并且只对选择进行区分?请检查合并查询,如果对您的用例有任何帮助。我正在考虑同时运行选择和更新,并将插入推送到队列中,以便稍后在队列满时可以运行批量插入。但我现在担心的是,选择和更新将需要我运行数据库连接?池会有帮助吗?最坏的情况是,如果所有请求都是update not insert,那么队列将没有帮助。合并查询将在单个查询中解决,无需选择和更新。我检查mysql上不支持合并查询。我同意,并且我知道每个设备都会尝试连接到数据库。我正在考虑排队,但我仍然需要进行选择和更新,因此我仍然需要数据库连接。是否可以为多个连接运行选择和更新,并且只对选择进行区分?请检查合并查询,如果对您的用例有任何帮助。我正在考虑同时运行选择和更新,并将插入推送到队列中,以便稍后在队列满时可以运行批量插入。但我现在担心的是,选择和更新将需要我运行数据库连接?池是否有用?最坏的情况是,如果所有请求都是update not insert,则队列将不起作用。合并查询将在单个查询中解决,无需选择和更新。检查mysql上不支持合并查询。委托给REST端点或发布到消息队列。无论哪种方式,其他一些服务器集群都会处理请求/消息以与数据库交互。每个请求/消息都很小,应该很快,因此数据库连接应该只借用几毫秒。随着通信量的增加,将节点添加到集群。@AndrewS那么你是说,在我对db执行select和update之后,我只是为了插入而将其推入队列,是吗?但是我的select和update语句呢?即使我添加了节点,db可以选择并发选择和更新吗?而不知道SQ