"pool" Phoenix 查询服务器连接的正确方法是什么

What is the correct way to "pool" the Phoenix Query Server connections

我们正在使用 Azure 和 Phoenix 写入 HBase 集群。有两个驱动程序:一个大驱动程序和一个瘦客户端。瘦客户端使用 Json 通过 HTTP 与数据库交互。

当我们创建一个新连接时,每次保存我们可以节省大约 150 毫秒。

this.conn = DriverManager.getConnection("jdbc:phoenix:thin:url=http://1.1.1.1");

当我们重用连接时,我们可以在每次保存 70 毫秒内完成:显着加速。文档有点模糊,并且在胖客户端和思考客户端之间转换。

那么,什么是池化瘦客户端连接的最佳实践?

重要变更!

我们开始遇到一些连接问题,所以我想回到我们的代码并进行一些更改。我设置了一些计时器,发现上面的代码在 0ms 内有效。我不确定我在上面做错了什么。

所以池化 Phoenix 的正确方法是不池化 Phoenix。有几篇来自开发团队的帖子证实了这一点。

拥有巨大的 SQL Oracle/DB2/SqlServer 背景可能是我的失败。使用 Redis 或 Phoenix 或任何新的 No-sql 数据库与 SQL 有很大不同。我的建议是 "read the directions" 你正在使用的产品,按照他们告诉你的去做!

根据 the FAQ from the Phoenix offical site,没有必要汇集 Phoenix JDBC 连接。

Phoenix’s Connection objects are different from most other JDBC Connections due to the underlying HBase connection. The Phoenix Connection object is designed to be a thin object that is inexpensive to create. If Phoenix Connections are reused, it is possible that the underlying HBase connection is not always left in a healthy state by the previous user. It is better to create new Phoenix Connections to ensure that you avoid any potential issues.

Implementing pooling for Phoenix could be done simply by creating a delegate Connection that instantiates a new Phoenix connection when retrieved from the pool and then closes the connection when returning it to the pool (see PHOENIX-2388).

我认为上面加粗的内容是瘦客户端连接池的最佳实践。

您可以尝试在客户端设置以下配置来调整性能,请参阅 Configuration and Tuning 了解更多详情。


更新:下面是我对 Phoenix 连接池的简单实现

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public class DataSource {

    private String driverClass;
    private String jdbcUrl;
    private String user;
    private String password;
    private int min; // The number of connections of initial pool
    private int max;
    private int used; // The number of connections of polled and not released from poll
    private Queue<Connection> pool = null;

    public DataSource(String driverClass, String jdbcUrl, String user, String password, int min, int max) {
        this.driverClass = driverClass;
        this.jdbcUrl = jdbcUrl;
        this.user = user;
        this.password = password;
        this.min = min;
        this.max = max;
        this.used = 0;
        this.pool = new ConcurrentLinkedQueue<Connection>();
        init();
    }

    private void init() {
        try {
            Class.forName(driverClass);
            for (int i = 0; i < min; i++) {
                Connection conn = DriverManager.getConnection(jdbcUrl, user, password);
                pool.add(conn);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public Connection getConnection() {
        Connection conn  = null;
        if (pool.size() > 0) {
            conn = pool.poll();
            Thread connGen = new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        Connection conn = DriverManager.getConnection(jdbcUrl, user, password);
                        pool.add(conn);
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            });
            connGen.start();
            used ++;
        } else if(used < max) {
            try {
                conn = DriverManager.getConnection(jdbcUrl, user, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return conn;
    }

    public void releaseConnection(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
                used--;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}