今天迎来了元宵节,也意味着今年的春节在今天正式结束了。不过很遗憾,笔者没有吃到汤圆。下班后匆匆煮了个面条,就又在往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不会是连续的。