逍遥谷

记录日常的点点滴滴

0%

Dinky部署

Dinky 不依赖任何外部的 Hadoop 或者 Flink 环境,可以单独部署在 flink、 hadoop 和 K8S 集群之外,完全解耦,支持同时连接多个不同的集群实例进行运维。

1
2
3
tar -zxvf dinky-release-{version}.tar.gz
mv dinky-release-{version} dinky
cd dinky

配置文件

创建好数据库后,修改 Dinky 连接 mysql 的配置文件。

1
2
3
#切换目录
cd /opt/dinky/config/
vim application.yml

加载依赖

Dinky 需要具备自身的 Flink 环境,该 Flink 环境的实现需要用户自己在 Dinky 根目录下 plugins/flink${FLINK_VERSION} 文件夹并上传相关的 Flink 依赖,如 flink-dist, flink-table 等,具体见下文。当然也可在启动文件中指定 FLINK_HOME,但不建议这样做。

注意事项

Dinky 当前版本的 yarn 的 perjob 与 application 执行模式依赖 flink-shade-hadoop ,如果你的 Hadoop 版本为 2+ 或 3+,需要额外添加 flink-shade-hadoop-uber-3 包,请手动删除该包内部的 javax.servlet 等冲突内容。 当然如果你的 Hadoop 为 3+ 也可以自行编译对于版本的 dinky-client-hadoop.jar 以替代 uber 包

将 flink-shade-hadoop 上传到到 plugins 文件目录下,使用 flink-shade-hadoop-3 地址如下:

阅读全文 »

需求

软件需求

Flink 运行在所有类 UNIX 环境下,例如 LinuxMac OS XCygwin (Windows),集群由一个 master 节点以及一个或多个 worker 节点构成。在配置系统之前,请确保在每个节点上安装有以下软件:

  • Java 1.8.x 或更高版本,
  • ssh (必须运行 sshd 以执行用于管理 Flink 各组件的脚本)

如果集群不满足软件要求,那么你需要安装/更新这些软件。

使集群中所有节点使用免密码 SSH 以及拥有相同的目录结构可以让你使用脚本来控制一切。

JAVA_HOME配置

Flink 需要 master 和所有 worker 节点设置 JAVA_HOME 环境变量,并指向你的 Java 安装目录。

你可以在 conf/flink-conf.yaml 文件中通过 env.java.home 配置项来设置此变量。

Flink设置

阅读全文 »

前置准备工作

外部软件安装:

  • JDK:下载JDK (1.8+),安装并配置 JAVA_HOME 环境变量,并将其下的 bin 目录追加到 PATH 环境变量中。如果你的环境中已存在,可以跳过这步。
  • 二进制包:在下载页面下载 DolphinScheduler 二进制包
  • 数据库:PostgreSQL (8.2.15+) 或者 MySQL (5.7+),两者任选其一即可,如 MySQL 则需要 JDBC Driver 8.0.16
  • 注册中心:ZooKeeper (3.8.0+),下载地址
  • 进程树分析
    • macOS 安装pstree
    • Fedora/Red/Hat/CentOS/Ubuntu/Debian 安装psmisc

注意: DolphinScheduler 本身不依赖 Hadoop、Hive、Spark,但如果你运行的任务需要依赖他们,就需要有对应的环境支持

准备 DolphinScheduler 启动环境

配置用户免密及权限

创建部署用户,并且一定要配置 sudo 免密。以创建 dolphinscheduler 用户为例

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建用户需使用 root 登录
useradd dolphinscheduler

# 添加密码
echo "dolphinscheduler" | passwd --stdin dolphinscheduler

# 配置 sudo 免密
sed -i '$adolphinscheduler ALL=(ALL) NOPASSWD: NOPASSWD: ALL' /etc/sudoers
sed -i 's/Defaults requirett/#Defaults requirett/g' /etc/sudoers

# 修改目录权限,使得部署用户对二进制包解压后的 apache-dolphinscheduler-*-bin 目录有操作权限
chown -R dolphinscheduler:dolphinscheduler apache-dolphinscheduler-*-bin
chmod -R 755 apache-dolphinscheduler-*-bin

注意:

  • 因为任务执行服务是以 sudo -u {linux-user} 切换不同 linux 用户的方式来实现多租户运行作业,所以部署用户需要有 sudo 权限,而且是免密的。初学习者不理解的话,完全可以暂时忽略这一点
  • 如果发现 /etc/sudoers 文件中有 “Defaults requirett” 这行,也请注释掉

配置机器 SSH 免密登陆

阅读全文 »

部署要求

Linux操作系统版本需求

Linux系统 版本
CentOS 7.1及以上
Ubuntu 16.04及以上

软件需求

软件 版本
Java 1.8及以上
GCC 4.8.2及以上

操作系统安装要求

设置系统最大打开文件句柄数

1
2
3
vi /etc/security/limits.conf 
* soft nofile 65536
* hard nofile 65536

时钟同步

Doris 的元数据要求时间精度要小于5000ms,所以所有集群所有机器要进行时钟同步,避免因为时钟问题引发的元数据不一致导致服务出现异常。

阅读全文 »

记一次处理生产同事使用MySQL8存储过程进行数据计算,各种笛卡尔积产生了大量中间数据,一个单表数据就超过了180GB,因为这张表的处理超时,事务死锁,导致整个依赖这个中间数据表的下游任务均受影响,生产上紧急处理这张表带来的问题,挑战删除这张大表。

建立硬链接

找到MySQL的数据文件中这张表对应的数据文件,假设表名是test,数据文件对应的是test.frm和test.ibd,通过查看test.ibd文件大小已经超过180GB,这就是这张表无法直接drop的原因。

在这个文件夹下,为test.frm和test.ibd分别建立硬链接

1
2
ln test.frm test.frm.h
ln test.ibd test.ibd.h

成功建立两个文件的硬链接

删除表

在MySQL中使用DROP 命令删除表

1
DROP TABLE test;

这时候删除非常快,立马就能删除完成

阅读全文 »

字符串整型相互转换

1
2
String a = String.valueOf(2);//integer to numeric string
int i = Integer.parseInt(a);//numeric string to an int

向文件末尾添加内容

1
2
3
4
5
6
7
8
9
10
11
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(”filename”, true));
out.write(”aString”);
} catch (IOException e) {
// error processing code
} finally {
if (out != null) {
out.close();
}
}

得到当前方法名

1
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();

字符串转换为日期

1
2
SimpleDateFormat format = new SimpleDateFormat( "dd.MM.yyyy" );
Date date = format.parse( myString );

使用JDBC访问Oracle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
* <p></p>
* @author z```s
* @version 1.0.0
* @since java8
* 2023-11-22 14:23
*/
public class OracleJdbcTest {

String driverClass = "oracle.jdbc.driver.OracleDriver";

Connection connection;

public void init(FileInputStream fs) throws ClassNotFoundException, SQLException, IOException {
Properties props = new Properties();
props.load(fs);
String url = props.getProperty("db.url");
String userName = props.getProperty("db.user");
String password = props.getProperty("db.password");
Class.forName(driverClass);
connection = DriverManager.getConnection(url, userName, password);
}

public void fetch() throws SQLException {
PreparedStatement ps = connection.prepareStatement("select SYSDATE from dual");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
// do the thing you do
}
rs.close();
ps.close();
}

public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException {
OracleJdbcTest test = new OracleJdbcTest();
test.init(null);
test.fetch();
}

}
阅读全文 »

KVM简介

KVM 全称是 Kernel-Based Virtual Machine。也就是说 KVM 是基于 Linux 内核实现的。
KVM有一个内核模块叫 kvm.ko,只用于管理虚拟 CPU 和内存。

那 IO 的虚拟化,比如存储和网络设备由谁实现呢?
这个就交给 Linux 内核和Qemu来实现。

作为一个 Hypervisor,KVM 本身只关注虚拟机调度和内存管理这两个方面。IO 外设的任务交给 Linux 内核和 Qemu。

KVM安装

查看CPU是否支持虚拟化

1
[root@localhost ~]# grep -E '(vmx|svm)' /proc/cpuinfo **

安装qemu-kvm(用户态管理工具),libvirt(命令行管理工具),virt-install(安装kvm工具),bridge-utils(桥接设备管理工具)

1
[root@localhost ~]# yum install -y qemu-kvm libvirt virt-install bridge-utils

确保加载kvm模块

阅读全文 »

配置防火墙,开启FTP服务需要的端口

1
2
systemctl stop firewalld #停止firewall
systemctl disable firewalld #禁止firewall开机启动

关闭SELINUX

1
2
3
4
5
6
7
8
9
10
11
vi /etc/selinux/config

#SELINUX=enforcing #注释掉

#SELINUXTYPE=targeted #注释掉

SELINUX=disabled #增加

:wq! #保存退出

setenforce 0 #使配置立即生效

安装vsftpd

1
2
3
4
5
6
7
8
9
rpm -qc vsftpd #查询vsftpd是否安装

yum install -y vsftpd #安装vsftpd

yum install -y psmisc net-tools systemd-devel libdb-devel perl-DBI #安装vsftpd虚拟用户配置依赖包

systemctl start vsftpd.service #启动

systemctl enable vsftpd.service #设置vsftpd开机启动

新建系统用户vsftpd

1
2
3
useradd vsftpd -d /home/wwwroot -s /bin/false #用户目录为/home/wwwroot, 用户登录终端设为/bin/false(即使之不能登录系统)

chown vsftpd:vsftpd /home/wwwroot -R

建立虚拟用户个人vsftpd的配置文件和子账号FTP权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
mkdir /etc/vsftpd/vconf

cd /etc/vsftpd/vconf

touch web1 #这里创建虚拟用户配置文件

mkdir -p /home/wwwroot/web1/http/mydic
 #设置FTP上传文件新增权限,最新的vsftpd要求对主目录不能有写的权限所以ftp为755,主目录下面的子目录再设置777权限

chmod -R 755 /home/wwwroot/web1/http
chmod R 777 /home/wwwroot/web1/http/mydic

vi web1 #编辑用户web1配置文件,其他的跟这个配置文件类似,输入下面红色内容
 local_root=/home/wwwroot/web1/http/  #设置FTP账号根目录

 write_enable=YES

anon_world_readable_only=NO

anon_upload_enable=YES

anon_mkdir_write_enable=YES

anon_other_write_enable=YES

:wq! #保存退出
阅读全文 »

软链接

创建软链接

1
ln -s 【目标目录】 【软链接地址】

【目标目录】指软链接指向的目标目录,【软链接地址】指“快捷键”文件名称,该文件是指被指令创建的。

删除软连接

1
rm -rf 【软链接地址】

上述指令中,软链接地址最后不能含有“/”,当含有“/”时,删除的是软链接目标目录下的资源,而不是软链接本身。

修改软连接

1
ln -snf 【新目标目录】 【软链接地址】

这里修改是指修改软链接的目标目录

阅读全文 »

Maven引入Jackson

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<properties>
<jackson.version>xxx</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-smile</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-cbor</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>

具体代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

/**
* <p></p>
* @author z```s
* @version 1.0.0
* @since java8
* 2020/5/11 10:45
*/
public class JSON {

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

public static final String DATE_TIME_FORMAT_01 = "yyyy-MM-dd HH:mm:ss";

public static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat(DATE_TIME_FORMAT_01);

static {
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//OBJECT_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
simpleModule.addSerializer(Double.class, ToStringSerializer.instance);
simpleModule.addSerializer(Double.TYPE, ToStringSerializer.instance);
simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT_01)));
simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT_01)));
OBJECT_MAPPER.registerModule(simpleModule);
}

private JSON() {
}

/**
* 将json文件转换为JSON对象
* @param filePath
* @param clazz
* @param <T>
* @return
*/
public static <T> T jsonFileParseObject(String filePath, Class<T> clazz) {
try {
return OBJECT_MAPPER.readValue(new File(filePath), clazz);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

/**
* 对象转换JSON字符串
* @param object
* @return
*/
public static String toJSONString(Object object) {
try {
return OBJECT_MAPPER.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}

/**
* JSON字符串转换对象
* @param text
* @param clazz
* @param <T>
* @return
*/
public static <T> T parseObject(String text, Class<T> clazz) {
try {
return OBJECT_MAPPER.readValue(text, clazz);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}

/**
* JSON字符串转换为List
* @param text
* @param <T>
* @return
*/
public static <T> List<T> parseArray(String text) {
TypeReference<ArrayList<T>> typeReference = new TypeReference<ArrayList<T>>() {};
try {
return OBJECT_MAPPER.readValue(text, typeReference);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}

/**
* JSON字符串转换为Map
* @param text
* @return
*/
public static <T> LinkedHashMap<String, T> parseMap(String text) {
TypeReference<LinkedHashMap<String, T>> typeReference = new TypeReference<LinkedHashMap<String, T>>() {};
try {
return OBJECT_MAPPER.readValue(text, typeReference);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}

}
阅读全文 »