元宵快乐,分享TiDB单节点的安装方法并使用Java进行CRUD操作

今天迎来了元宵节,也意味着今年的春节在今天正式结束了。不过很遗憾,笔者没有吃到汤圆。下班后匆匆煮了个面条,就又在往git提交代码了(rsw)。

时间飞快,眼看着夜间10点了,笔者一脸茫然,于是总结下今天学的TiDB。

这里特别说明,目前学习和测试用的还是单节点版(这里关系着一个TiDB使用场景,有这样一个说法:MySQL单节点能搞定的就不需要用TiDB、5000W以下的数据也不需要TiDB,因此说明TiDB非常适合分布式集群场景。不过只是为了学习也弄不到那么多服务器来做集群,单节点使用方式与集群也都一样,所以这里直接用单节点的安装方式来学习)。

现在开始记录TiDB的安装方法:

官方推荐操作系统版本Linux ( Redhat 7+,CentOS 7+ )

# 下载二进制压缩包
wget http://download.pingcap.org/tidb-latest-linux-amd64.tar.gz
wget http://download.pingcap.org/tidb-latest-linux-amd64.sha256

# 检查文件完整性
sha256sum -c tidb-latest-linux-amd64.sha256

# 解压缩
tar -xzf tidb-latest-linux-amd64.tar.gz
cd tidb-latest-linux-amd64/

由于是直接下载二进制安装包的,所以解压后就表示安装好了。在tidb-latest-linux-amd64目录下回看到一个bin文件夹。

下面以单节点的方式启动TiDB

步骤一、启动PD
./bin/pd-server --data-dir=pd --log-file=pd.log
步骤二、启动TiKV
./bin/tikv-server --pd="127.0.0.1:2379" --data-dir=tikv --log-file=tikv.log
步骤三、启动TiDB
./bin/tidb-server --store=tikv --path="127.0.0.1:2379" --log-file=tidb.log
步骤四、连接TiDB

这里很神奇,我们用的是MySQL客户端去连接,因为TiDB基本上是兼容MySQL协议的。

mysql -h 127.0.0.1 -P 4000 -u root -D test

默认端口是4000而非MySQL的3396,用户是root 没用密码。另外使用Navicat等工具也是可以直接连接TiDB的。

现在用Java对TiDB进行crud操作

步骤一、创建数据库k2s和t_user表
create database k2s;
use k2s;
CREATE TABLE `t_user` (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `email` varchar(32) NOT NULL,
  `create_date` datetime DEFAULT NULL,
  `update_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
步骤二、编写Test.java代码连接TiDB和crud操作
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;

/**
 * @author dev-tang <dev-tang@outlook.com> on 18-3-2.
 */
public class Test {

    private Connection connection;

    private int executeUpdate(String sql, Object... args) throws SQLException {
        int affectedRow = 0;
        PreparedStatement statement = connection.prepareStatement(sql);
        try {
            for (int i = 0; i < args.length; i++) {
                statement.setObject(i + 1, args[i]);
            }
            affectedRow = statement.executeUpdate();
        } finally {
            if (statement != null) {
                statement.close();
            }
        }
        return affectedRow;
    }

    public int insert(String sql, Object... args) throws SQLException {
        return executeUpdate(sql, args);
    }

    public int update(String sql, Object... args) throws SQLException {
        return executeUpdate(sql, args);
    }

    public int delete(String sql, Object... args) throws SQLException {
        return executeUpdate(sql, args);
    }

    public List<Map<String, Object>> queryForList(String sql, Object... args) throws SQLException {
        List<Map<String, Object>> resultList = new ArrayList<>();

        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                statement.setObject(i + 1, args[i]);
            }

            resultSet = statement.executeQuery();
            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();

            int count = resultSetMetaData.getColumnCount();
            String columnNames[] = new String[count];
            for (int i = 1; i <= count; i++) {
                columnNames[i - 1] = resultSetMetaData.getColumnName(i);
            }

            while (resultSet.next()) {
                Map<String, Object> resultMap = new HashMap<>();
                for (String name : columnNames) {
                    resultMap.put(name, resultSet.getObject(name));
                }
                resultList.add(resultMap);
            }
        } finally {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
        }

        return resultList;
    }

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Test test = new Test();
        Class.forName("com.mysql.jdbc.Driver");
        test.connection = DriverManager.getConnection("jdbc:mysql://localhost:4000/k2s", "root", "");
        int row = test.insert("insert into t_user(email, create_date) values(?, ?)", new Object[]{"dev-tang@outlook.com", new Date()});
        System.out.println(row);

        List<Map<String, Object>> resultList = test.queryForList("select * from t_user");
        for (Map<String, Object> resultMap : resultList) {
            for (Map.Entry<String, Object> e : resultMap.entrySet()) {
                System.out.println(e.getKey() + ": " + e.getValue());
            }
        }

        test.connection.close();
    }
}

直接运行Test类的main方法,会先向TiDB的k2s.t_user表插入一条数据,然后在查询出来。为了方便这里封装了几个简单的JDBC操作方法,并且在查询时返回List<Map<String, Object>>对象。

TiDB自增ID只保证唯一性,不保证连续性分配。TiDB目前采用批量分配的方式,因此在多台TiDB上插入的数据,自增ID不会是连续的。

本博客采用 知识共享署名-禁止演绎 4.0 国际许可协议 进行许可

本文标题:元宵快乐,分享TiDB单节点的安装方法并使用Java进行CRUD操作

本文地址:https://jizhong.plus/post/2018/03/tidb-install-and-use.html