Tous les produits
Search
Centre de documentation

E-MapReduce:Phoenix

Dernière mise à jour :Aug 09, 2026

Apache Phoenix est une couche SQL intégrée à HBase qui vous permet d'utiliser le langage SQL standard pour interroger et gérer les données stockées dans HBase.

Prérequis

Vous avez créé un cluster DataServing ou personnalisé en sélectionnant les services Phoenix et HBase. Pour plus d'informations, consultez la rubrique Créer un cluster.

Utiliser Phoenix en ligne de commande

  1. Connectez-vous au cluster via SSH. Pour plus d'informations, consultez la rubrique Se connecter à un cluster.

  2. Exécutez la commande suivante pour utiliser l'outil de ligne de commande Phoenix.

    /opt/apps/PHOENIX/phoenix-current/bin/sqlline.py
  3. Interrogez les données avec le langage SQL. Voici quelques opérations courantes :

    • Création d'une table

      CREATE TABLE IF NOT EXISTS example(
          my_pk bigint not null,
          m.first_name varchar(50),
          m.last_name varchar(50) 
          CONSTRAINT pk PRIMARY KEY (my_pk)
      );
    • Insertion de données

      UPSERT INTO example(my_pk,m.first_name,m.last_name) VALUES(100,'Jack','Ben');
      UPSERT INTO example(my_pk,m.first_name,m.last_name) VALUES(200,'Jack3','Ben3');
    • Interrogation des données

      SELECT * FROM example;

      La requête renvoie le résultat suivant :

      +--------+-------------+------------+
      | MY_PK  | FIRST_NAME  | LAST_NAME  |
      +--------+-------------+------------+
      | 100    | Jack        | Ben        |
      | 200    | Jack3       | Ben3       |
      +--------+-------------+------------+
    • Suppression de la table

      DROP TABLE IF EXISTS example;

Se connecter à Phoenix via JDBC

Configurer la dépendance Maven

<dependency>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix-core</artifactId>
     <version>${phoenix.version}</version>
</dependency>

La valeur ${phoenix.version} doit correspondre à la version de Phoenix installée sur votre cluster.

Exemple de code

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;
public class TestPhoenixJdbc {
    public static void main(String[] args) throws SQLException {
        Statement stmt = null;
        ResultSet rset = null;
        Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
        Connection con = DriverManager.getConnection("jdbc:phoenix:[zookeeper quorum hosts]");
        stmt = con.createStatement();
        stmt.executeUpdate("create table test (mykey integer not null primary key, mycolumn varchar)");
        stmt.executeUpdate("upsert into test values (1,'Hello')");
        stmt.executeUpdate("upsert into test values (2,'World!')");
        con.commit();
        PreparedStatement statement = con.prepareStatement("select * from test");
        rset = statement.executeQuery();
        while (rset.next()) {
            System.out.println(rset.getString("mycolumn"));
        }
        statement.close();
        con.close();
    }
}

Se connecter à un cluster Phoenix activé pour Kerberos via JDBC

Si votre cluster utilise l'authentification Kerberos, cette section explique comment développer un client JDBC capable de se connecter en toute sécurité au service Phoenix d'un cluster EMR activé pour Kerberos. Le client utilise une URL JDBC contenant les informations de principal et de keytab pour s'authentifier, puis exécute des opérations DDL et DML de base afin de vérifier la connexion.

Étape 1 : Préparer l'environnement et les identifiants

Avant d'écrire le code, configurez votre environnement et créez les identifiants Kerberos sur le nœud maître du cluster.

  1. Connectez-vous au nœud maître via SSH. Pour plus d'informations, consultez la rubrique Se connecter à un cluster.

  2. Identifiez le domaine Kerberos (realm).

    Chaque cluster activé pour Kerberos possède un domaine unique.

    Exécutez la commande suivante pour récupérer le domaine Kerberos. Notez-le pour une utilisation ultérieure.

    cat /etc/krb5.conf | grep default_realm

    Voici un exemple de réponse :

    default_realm = EMR.C-4FC5FDDE3759****.COM
  3. Créez un principal client.

    Un principal représente l'identité unique d'un client dans Kerberos. Vous devez créer un principal pour l'application Java.

    1. Sur le nœud maître, exécutez la commande suivante pour utiliser l'outil kadmin.local.

      sudo kadmin.local
    2. Dans la session interactive kadmin.local, exécutez la commande suivante pour créer le principal.

      addprinc phoenix_client@EMR.C-4FC5FDDE3759****.COM

      Lorsque vous y êtes invité, définissez un mot de passe pour le principal et notez-le. Bien que le fichier keytab permette une connexion sans mot de passe, ce dernier peut parfois être requis.

  4. Exportez le fichier keytab.

    1. Dans l'outil kadmin.local, exécutez la commande suivante pour exporter le fichier keytab.

      xst -k /tmp/phoenix_client.keytab phoenix_client@EMR.C-4FC5FDDE3759****.COM
    2. Exécutez la commande suivante pour quitter kadmin.local.

      exit
      Important
      • Autorisations : assurez-vous que l'utilisateur exécutant le programme Java dispose des autorisations de lecture sur le fichier keytab.

      • Distribution : si votre programme Java s'exécute sur une machine différente, copiez de manière sécurisée le fichier phoenix_client.keytab et le fichier /etc/krb5.conf vers cette machine, et assurez-vous qu'ils se trouvent dans un chemin accessible à l'application.

Étape 2 : Écrire et empaqueter l'application

  • Méthode 1 : Utiliser un fichier JAR précompilé (vérification rapide)

    hbase-phoenix-kerberos-1.0-SNAPSHOT.jar

  • Méthode 2 : Compiler et empaqueter manuellement (recommandé pour la production)

    Vous pouvez utiliser l'exemple de code suivant pour la compilation et l'empaquetage manuels.

    Exemple de code principal (PhoenixKerberosDemo.java)

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    /**
     * A client that connects to a Kerberos-secured Phoenix cluster using JDBC.
     * All connection parameters are provided through a complete JDBC URL passed from the command line.
     */
    public class PhoenixKerberosDemo {
        /**
         * The main entry point for the application.
         *
         * @param args Command-line arguments. The program expects one argument: the complete Phoenix JDBC URL.
         */
        public static void main(String[] args) {
            // --- 1. Validate command-line input: Expect one argument, the JDBC URL ---
            if (args.length != 1) {
                System.err.println("ERROR: Invalid number of arguments.");
                System.err.println("Usage: java PhoenixKerberosDemo \"<full_jdbc_url>\"");
                System.err.println("Example: \"jdbc:phoenix:zk1,zk2:2181:/hbase:user@REALM.COM:/path/to/user.keytab\"");
                System.exit(1); // Exit with an error code
            }
            String jdbcUrl = args[0];
            System.out.println("Attempting to connect to Phoenix...");
            System.out.println("Using JDBC URL: " + jdbcUrl);
            try {
                // --- 2. Load the Phoenix driver ---
                Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
            } catch (ClassNotFoundException e) {
                System.err.println("FATAL ERROR: Phoenix JDBC driver not found in the classpath.");
                e.printStackTrace();
                System.exit(1);
            }
            // --- 3. Use a try-with-resources statement to establish a connection and execute SQL. This syntax automatically closes resources. ---
            try (Connection con = DriverManager.getConnection(jdbcUrl);
                 Statement stmt = con.createStatement()) {
                System.out.println("Connection established successfully.");
                final String tableName = "TEST";
                System.out.println("Creating table '" + tableName + "'...");
                stmt.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " (mykey INTEGER NOT NULL PRIMARY KEY, mycolumn VARCHAR)");
                con.commit();
                System.out.println("Upserting data...");
                stmt.executeUpdate("UPSERT INTO " + tableName + " VALUES (1, 'Hello')");
                stmt.executeUpdate("UPSERT INTO " + tableName + " VALUES (2, 'World-Kerberos!')");
                con.commit();
                System.out.println("Data upserted successfully.");
                String sql = "SELECT * FROM " + tableName;
                System.out.println("Querying for results with: " + sql);
                try (PreparedStatement statement = con.prepareStatement(sql);
                     ResultSet rset = statement.executeQuery()) {
                    System.out.println("Query results:");
                    while (rset.next()) {
                        System.out.println(rset.getInt("mykey") + " -> " + rset.getString("mycolumn"));
                    }
                }
                System.out.println("Cleaning up the test table...");
                stmt.executeUpdate("DROP TABLE IF EXISTS " + tableName);
                con.commit();
            } catch (SQLException e) {
                // Catch SQL exceptions and provide helpful troubleshooting tips
                System.err.println("\n--- FAILED TO EXECUTE DATABASE OPERATION ---");
                System.err.println("Please check the following:");
                System.err.println("1. The JDBC URL is correct (format, principal, keytab path).");
                System.err.println("2. Network connectivity to ZooKeeper and HBase.");
                System.err.println("3. The keytab file exists and has correct read permissions.");
                System.err.println("4. The principal has sufficient permissions on HBase tables and namespaces.");
                e.printStackTrace();
            }
            System.out.println("\nExecution finished.");
        }
    }
    

    Configuration Maven (pom.xml)

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                                 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.aliyun.emr.doctor</groupId>
        <artifactId>hbase-phoenix-kerberos</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>Archetype - hbase-phoenix-kerberos</name>
        <url>http://maven.apache.org</url>
        <properties>
            <phoenix.version>5.2.1</phoenix.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.apache.phoenix</groupId>
                <artifactId>phoenix-core</artifactId>
                <version>${phoenix.version}</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <!--  Java Compiler  -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.2.4</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                            <configuration>
                                <filters>
                                    <filter>
                                        <artifact>*:*</artifact>
                                        <excludes>
                                            <exclude>META-INF/*.SF</exclude>
                                            <exclude>META-INF/*.DSA</exclude>
                                            <exclude>META-INF/*.RSA</exclude>
                                        </excludes>
                                    </filter>
                                </filters>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>

Étape 3 : Exécuter l'application

  1. Choisissez un environnement d'exécution.

    Sélectionnez l'un des deux environnements d'exécution suivants :

    • Exécution sur un nœud du cluster (recommandée) :

      • Les nœuds du cluster disposent des bibliothèques de dépendances Hadoop, HBase et Phoenix requises, préinstallées. Aucune configuration supplémentaire n'est nécessaire. La connectivité réseau est également disponible par défaut, offrant ainsi un environnement complet et stable.

      • Idéal pour : la vérification rapide et les tests lors du développement et du débogage.

    • Exécution hors du cluster

      Pour exécuter le programme hors du cluster, assurez-vous que les conditions suivantes sont remplies :

      • Connectivité réseau : assurez-vous que la machine exécutant le programme peut communiquer avec les nœuds ZooKeeper, HBase Master et RegionServer du cluster.

      • Configuration Kerberos : copiez le fichier krb5.conf du cluster ainsi que le fichier keytab généré vers la machine où le programme s'exécute.

      • Gestion des dépendances : le classpath de la commande d'exécution doit inclure tous les fichiers JAR de dépendance client Hadoop, HBase et Phoenix requis. Cette étape est généralement plus complexe que l'exécution sur un nœud du cluster. Nous vous recommandons d'utiliser un outil tel que Maven ou Gradle pour la gestion des dépendances.

  2. Exécutez le script.

    Le script kerberos-phoenix.sh suivant inclut tous les paramètres requis. Vous pouvez le modifier et l'exécuter selon vos besoins.

    #!/bin/bash
    # ======================= 1. User configuration (modify based on your environment) =======================
    # Directory for Hadoop and HBase configuration files
    HADOOP_CONF_DIR="/etc/taihao-apps/hadoop-conf"
    HBASE_CONF_DIR="/etc/taihao-apps/hbase-conf"
    # Path to the Phoenix client JAR file. Using a symbolic link is a best practice to stay resilient to version changes.
    # First, confirm this file exists by using `ls -l /opt/apps/PHOENIX/phoenix-current/`. This path may need to be modified for different versions.
    PHOENIX_JAR="/opt/apps/PHOENIX/phoenix-current/phoenix-client-lite-hbase-2.6.jar"
    # Your application's JAR file name.
    YOUR_JAR_FILE="hbase-phoenix-kerberos-1.0-SNAPSHOT.jar"
    # Path to the Kerberos configuration file.
    KRB5_CONF_PATH="/etc/krb5.conf"
    # --- [Core] JDBC URL configuration ---
    # Format: jdbc:phoenix:[ZK Address]:[ZK Port]:[HBase ZNode]:[Principal]:[Absolute Keytab Path]
    # Replace the ZK address, REALM, and keytab path below with your actual information.
    ZK_QUORUM="master-1-1" # If there are multiple ZooKeeper nodes, separate them with commas, for example, "zk1,zk2,zk3"
    ZK_PORT="2181"
    HBASE_ZNODE="/hbase" # For a secure cluster, it might be /hbase-secure
    PRINCIPAL="phoenix_client@EMR.C-4FC5FDDE3759****.COM" # Replace with your principal
    KEYTAB_PATH="/tmp/phoenix_client.keytab" # Absolute path to the keytab file
    JDBC_URL="jdbc:phoenix:${ZK_QUORUM}:${ZK_PORT}:${HBASE_ZNODE}:${PRINCIPAL}:${KEYTAB_PATH}"
    # =================================================================================
    # ======================= 2. Execution (usually no changes needed) =================================
    echo "================================================="
    echo "Starting Phoenix Kerberos JDBC Demo..."
    echo "Using JDBC URL: ${JDBC_URL}"
    echo "================================================="
    # Build the classpath. Order: current directory -> configuration directories -> your JAR -> dependency JARs
    # `hbase classpath` automatically loads core Hadoop/HBase dependencies
    CLASS_PATH=".:${HADOOP_CONF_DIR}:${HBASE_CONF_DIR}:${YOUR_JAR_FILE}:${PHOENIX_JAR}:$(hbase classpath)"
    # Execute the Java program
    java -cp "${CLASS_PATH}" \
         -Djava.security.krb5.conf="${KRB5_CONF_PATH}" \
         PhoenixKerberosDemo "${JDBC_URL}"
    # Check the exit code
    if [ $? -eq 0 ]; then
        echo -e "\n[SUCCESS] Program finished successfully."
    else
        echo -e "\n[FAILED] Program terminated with an error."
    fi
    # =================================================================================
    1. Téléchargez le fichier JAR empaqueté à l'étape 2 ainsi que le script kerberos-phoenix.sh dans un répertoire cible sur le nœud maître.

    2. Exécutez la commande suivante pour accorder les autorisations d'exécution au script.

      chmod +x kerberos-phoenix.sh
    3. Exécutez la commande suivante pour lancer le script.

      ./kerberos-phoenix.sh

      Voici un exemple de sortie :

      2025-08-13 13:22:30,825 INFO query.GuidePostsCacheProvider: Sucessfully loaded class for GuidePostsCacheFactor of type: org.apache.phoenix.query.DefaultGuidePostsCacheFactory
      2025-08-13 13:22:30,939 INFO connectionqueryservice.ConnectionQueryServicesMetricsManager: Created object for NoOp Connection query service metrics manager
      Connection established successfully.
      Creating table 'TEST'...
      2025-08-13 13:22:33,433 INFO client.HBaseAdmin: Operation: CREATE, Table Name: default:TEST, procId: 144 completed
      Upserting data...
      Data upserted successfully.
      Querying for results with: SELECT * FROM TEST
      Query results:
      1 -> Hello
      2 -> World-Kerberos!
      Cleaning up the test table...
      2025-08-13 13:22:33,597 INFO client.HBaseAdmin: Started disable of TEST
      2025-08-13 13:22:34,209 INFO client.HBaseAdmin: Operation: DISABLE, Table Name: default:TEST, procId: 147 completed
      2025-08-13 13:22:34,521 INFO client.HBaseAdmin: Operation: DELETE, Table Name: default:TEST, procId: 151 completed
      Execution finished.
      2025-08-13 13:22:34,559 INFO log.QueryLoggerDisruptor: Shutting down QueryLoggerDisruptor..
      2025-08-13 13:22:34,559 INFO client.ConnectionImplementation: Closing master protocol: MasterService
      2025-08-13 13:22:34,563 INFO hbase.ChoreService: Chore service for: AsyncConn Chore Service had [ScheduledChore name=RefreshCredentials, period=30000, unit=MILLISECONDS] on shutdown
      2025-08-13 13:22:34,563 INFO query.ConnectionQueryServicesImpl: hconnection-0x1fdf1c5 HConnection closed. Stacktrace for informational purposes: java.lang.Thread.getStackTrace(Thread.java:1564)
      org.apache.phoenix.util.LogUtil.getCallerStackTrace(LogUtil.java:55)
      org.apache.phoenix.query.ConnectionQueryServicesImpl.closeConnection(ConnectionQueryServicesImpl.java:537)
      org.apache.phoenix.query.ConnectionQueryServicesImpl.close(ConnectionQueryServicesImpl.java:649)
      org.apache.phoenix.jdbc.PhoenixDriver.close(PhoenixDriver.java:349)
      ...
      org.apache.phoenix.jdbc.PhoenixDriver.closeInstance(PhoenixDriver.java:138)
      org.apache.phoenix.jdbc.PhoenixDriver.access$000(PhoenixDriver.java:68)
      org.apache.phoenix.jdbc.PhoenixDriver$1$1.run(PhoenixDriver.java:94)
      java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
      java.util.concurrent.FutureTask.run(FutureTask.java:266)
      java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
      java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
      java.lang.Thread.run(Thread.java:750)
      [SUCCESS] Program finished successfully.

Références

Pour plus d'informations sur Phoenix, consultez la documentation officielle :