Kettle 使用记录

  1. 转换:在kettle转换中设置了变量,但是在后续的步骤中引用该变量不起作用?
    原因:是因为转换中的所有步骤都是并行运行的,没有特定的执行顺序。也就是说,设置的变量在当前转换里是不起作用的。解决:方法是在job里将设置变量作为一个前置的转换,然后将引用该变量的转换作为后置转换。
    kettle设置变量不起作用
  2. 作业:作业中的转换文件是否可以使用相对路径?
    转换文件名:必须填写,填写路径可以是绝对路径或者相对路径,本实例中是指定相对路径,通过Kettle自带的变量${Internal.Job.Filename.Directory}。
    参考:【Kettle从零开始】第六弹之Kettle作业流程使用
    补充:为什么往HDFS写会把kettle路径加进去,目前原因不明。处理:清理data-integration/system/karaf/caches目录,但每次运行前都要清理。(出自Kettle交流群)
  3. 空字符串更新/插入不允许NULL字段的时候报:Column ‘XXXXX’ cannot be null
    原因:默认情况下,kettle认为空字符串=NULL
    解决:找到kettle.properties文件,在文件中增加一行:KETTLE_EMPTY_STRING_DIFFERS_FROM_NULL=Y
    windows: 在C:\Users\用户名\.kettle目录中
    linux: 在~/.kettle目录中
  4. MYSQL时间字段出现:Value ‘0000-00-00 00:00:00’ can not be represented as java.sql.Timestamp
    解决:数据连接->选项->参数 中增加:(有这种字段的连接都要加)
    名:zeroDateTimeBehavior 值:convertToNull
    kettle Mysql处理timestamp数据格式数据异常
  5. 组件:值映射:可以根据某字段的值映射出一个新字段。
  6. 新建数据库连接,设置选项 characterEncoding:utf8mb4,提示:Unsupported character encoding ‘utf8mb4’.
    先设置选项:characterEncoding:utf8,然后去高级项目中的 -> 请输入连接成功后要执行的SQL:set names utf8mb4;
    参考:https://blog.csdn.net/bohai0409/article/details/38072465

根据系统时间获取数据:

发表在 mysql, 其它 | 标签为 , , | 留下评论

突破

突破自己,先装个蓝灯再说。:)

https://github.com/getlantern/lantern

 

注:windows版本的下载解压出来的需要自己在文件上加个.exe

发表在 其它 | 标签为 , | 留下评论

准备建立数据仓库

相关软件:

  1. mysql 用于存放数据
  2. otter 用于同步数据(主要用于多个数据库实例合并)
  3. kettle 用于数据ETL(主要用于数据抽取)
    kettle下载:https://community.hds.com/docs/DOC-1009855(去下边的Download里找下载连接)
    mysql驱动:https://dev.mysql.com/get/archives/mysql-connector-java-5.1/mysql-connector-java-5.1.41.tar.gz

发表在 mysql | 标签为 , | 留下评论

otter 安装过程记录

本次操作的目的是将多个实例的数据库合并到一个实例中去,为查询统计数据提供方便。

本文的操作系统是CentOs 7.

确定机器上已安装java. 如没有则先安装:
> yum install java-1.8.0-openjdk.x86_64

1。下载必要软件,这三个都是直接解压后就可运行。

http://mirrors.hust.edu.cn/apache/zookeeper/ — 下载最新的稳定版本
wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz

https://github.com/alibaba/otter/releases — 下载otter的manager 和 node,下载最新的稳定版本
wget https://github.com/alibaba/otter/releases/download/v4.2.15/manager.deployer-4.2.15.tar.gz — 下载manager
wget https://raw.github.com/alibaba/otter/master/manager/deployer/src/main/resources/sql/otter-manager-schema.sql — manager的mysql数据库结构
wget https://github.com/alibaba/otter/releases/download/v4.2.15/node.deployer-4.2.15.tar.gz — 下载node

2.官方参考文档:
https://github.com/alibaba/otter/wiki
https://github.com/alibaba/otter/wiki/QuickStart — 快速开始

3。安装MYSQL,将源数据库已有的数据导入到目标库中。在源库中执行otter-manager-schema.sql,建好otter数据库。建议不要放在同步目标数据库里。

4。解压
解压后的目录结构 /data/soft/zookeeper/zookeeper-3.4.13
/data/soft/otter/manager.deployer-4.2.15
/data/soft/otter/node.deployer-4.2.15

> tar -zvxf zookeeper-3.4.13.tar.gz
> tar -zvxf manager.deployer-4.2.15.tar.gz -C manager.deployer-4.2.15 – 解压到指定目录,要先把目录建好
> tar -zvxf node.deployer-4.2.15.tar.gz -C node.deployer-4.2.15 – 解压到指定目录

5.运行 zookeeper
复制配置文件:> cp zookeeper-3.4.13/conf/zoo_sample.cfg zookeeper-3.4.13/conf/zoo.cfg
修改配置:> vi zookeeper-3.4.13/conf/zoo.cfg
修改内容:
dataDir=/data/soft/zookeeper/data # 目录要先建好
dataLogDir=/data/soft/zookeeper/log
其它配置全部用默认

启动:> ./zookeeper-3.4.13/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /data/soft/zookeeper/zookeeper-3.4.13/bin/../conf/zoo.cfg
Starting zookeeper … STARTED

> netstat -na | grep 2181 看下zookeeper启动了没有

6.运行otter的manager
先确定otter-manager-schema.sql已在数据库执行完毕,otter库已经建好。
运行SQL的时候如果出现错误:
ERROR 1067 (42000): Invalid default value for ‘GMT_CREATE’
就打开otter-manager-schema.sql文件,
把全部的
`GMT_CREATE` timestamp NOT NULL DEFAULT ‘0000-00-00 00:00:00’
替换为:
`GMT_CREATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
这是因为mysql的sql_mode参数不允许timestamp类型的字段有0值出现造成的。

给otter库单独建一个帐号。
CREATE USER ‘otter’@’127.0.0.1’ IDENTIFIED BY ‘123456’;
GRANT all privileges ON otter.* TO ‘otter’@’127.0.0.1’;
flush privileges;

修改配置文件:> vi ./manager.deployer-4.2.15/conf/otter.properties
otter.domainName = xxx.xxx.xxx.xxx # 修改为正确访问ip(内网访问配置内网地址外网访问配置外网地址)
otter.port = 8081 # 修改http端口,允许公网访问的还是改下吧

otter.database.driver.username = otter # 改为安装了otter库的mysql的帐号
otter.database.driver.password = 123456 # 改为真实密码
otter.zookeeper.cluster.default = 127.0.0.1:2181 # 改为zookeeper的IP和端口,这里用默认因为zookeeper在同一机器上并且保持了默认设置

启动:./manager.deployer-4.2.15/bin/startup.sh
> netstat -na | grep 8081 看下manager启动了没有

问题:
1.启动失败提示:otter Service Unavailable # zookeeper没启动造成,或manager设置的zookeeper地址或端口不对.

7.配置otter的node,先不启动
修改配置文件:> vi ./node.deployer-4.2.15/conf/otter.properties
otter.manager.address = 127.0.0.1:1099 # manager所在机器的正确地址和端口,因为这里在同一台机器所以用默认

8。在manager中进行单向同步配置.
manager启动成功后,用浏览器打开地址: http://xxx.xxx.xxx.xxx:8081 # 在manager的otter.properties配置好的,如果打不开看下防火墙的端口是不是开了。
右上角点击登录图标,登录。默认帐号和密码是:admin:admin

8。1 zookeeper 添加
菜单:机器管理 -> zookeeper管理 -> 按钮:添加

表单填写,必填项
集群名字:# 填写一个明确的名字,如:本地zookeeper
ZooKeeper集群:127.0.0.1:2181; # 因为manager与zookeeper在同一台机器所以用本地IP(最后的分号不要漏掉)
保存

保存时可能出现的问题:
1。http error 500 problem accessing # otter的表所在库数据库没有写入权限,更改mysql帐号权限重启manager。
2。HTTP ERROR 500 #数据库帐号权限问题

Problem accessing /channelList.htm. Reason:

Failed to invoke Valve[#2/3, level 3]: com.alibaba.citrus.turbine.pipeline.valve.PerformTemplateScreenValve#4f3356c0:PerformTemplateScreenValve

8。2 node 添加
添加前,要确保zookeeper已启动。
菜单:机器管理 -> node管理 -> 按钮:添加

表单填写
机器名称:#有node.deployer-4.2.15的机器算为一个node,为这台机器起个名字
机器IP:10.81.83.130 # 对应node节点将要部署的机器ip,如果有多ip时,可选择其中一个ip进行暴露. (此ip是整个集群通讯的入口,实际情况千万别使用127.0.0.1,否则多个机器的node节点会无法识别)
机器端口:2088 # 对应node节点将要部署时启动的数据通讯端口,建议值:2088
下载端口:9090 # 对应node节点将要部署时启动的数据下载端口,建议值:9090
外部ip :对应node节点将要部署的机器ip,存在的一个外部ip,允许通讯的时候走公网处理。因为是内网这里留空。
zookeeper集群:选上一步建好的zookeeper
保存

保存完毕后,在列表里看下序号是几。我这里是1,按官方说的:
写入node的id文件:
> echo 1 > ./node.deployer-4.2.15/conf/nid # 多个node协同工作时不能重复

此时本条node记录的状态是:未启动

8.3 node 启动
> ./node.deployer-4.2.15/bin/startup.sh
然后刷新node管理列表,看下状态。正常情况下应该是:已启动

可能的问题:
如果状态不是已启动,看node的日志:
> vi ./node.deployer-4.2.15/logs/node/node.log

8。4 数据源配置
菜单:配置管理 -> 数据源配置 -> 按钮:添加

说明;这里用于配置源数据库和目标数据库。

表单填写:
数据源名字:给源或目标数据库起个名。源数据库(主库 master),目标数据库(从库 Slave)
用户名:mysql可用的帐号
密码:mysql帐号密码
URL:jdbc:mysql://10.20.144.15:3306 # 源或目标库的IP和端口
编码:与指定的数据库的默认编码一致。

验证下数据源:恭喜,数据库通过验证! — 表示成功

保存

8。5 数据表配置
菜单:配置管理 -> 数据表配置 -> 按钮:添加

说明:这里设置源或目标数据库要同步的表。如果源库已有表和数据,要先把现有的数据导入目标库,否则报错。

表单填写:
schmea name:要同步的数据库名,如果要同步多个库可用正则表达式:(a库|b库|c库…)
table name:要同步的表名,如果要同步多个表可用正则表达式:.*或(a表|b表|c表…)
数据源:选择源或目标数据源.

8.6 canal配置
菜单:配置管理 -> canal配置 -> 按钮:添加

说明:配置去主库复制数据的canal。

表单填写:
canal名称:起名
数据库地址:10.51.21.252:3306; # 填写主库IP与端口
数据库帐号:
数据库密码:
其它默认
保存

8.7 同步管理配置(把主从库关联起来的步骤)
8.7.1 新建Channel
菜单:同步管理 -> 按钮:添加

表单填写:
Channel Name:起名
其它默认
保存

8.7.2 Pipeline管理
点击 Channel名字 -> 按钮:添加

表单填写:
Pipeline名字:起名
Select机器:数据来源的Node机器 —– 离源mysql近的应为select机器,离目的mysql近的应为load(如果两个node选择的不一样的特别是异地的,安装aria2工具(在node节点之间提供文件传输通道)。)
Load机器:被同步的Node机器
Canal名字: 对应select机器的canal(即用于主从同步的canal)
其它默认
保存

8.7.3 映射关系列表
点击 Pipeline名字 -> 按钮:添加

说明:建立源库与目标库之间的映射关系。

表单填写:
源数据表:源数据库的数据源配置(主库 master)
目标数据表:目标数据库的数据源配置(从库 slave)
保存

8.7.4 启用Channel
菜单:同步管理 -> 启用

8.7.5 查看运行情况
菜单:监控管理 -> 日志记录,根据日志查看错误情况

问题处理:
1。pid:1 nid:1 exception:canal:测试库canal:com.alibaba.otter.canal.parse.exception.CanalParseException: Unsupported BinlogFormat STATEMENT
第一步:主库的binlog_format必须设置为Row.

第二步:把zookeeper停止,并把它的日志删除掉。[./zkServer.sh stop]
清掉manager所有数据表的内容(除帐号表),重启manager和node。
重新配置所有manager的内容。
然后,好了
关键,不知道问题点在哪里

2。DuplicateKeyException: PreparedStatementCallback; SQL [update `xxx`.`xxx_table` set `id` = ? where ( `id` = ? )]; Duplicate entry ‘785748’ for key ‘PRIMARY’;
2.1 先停止channel
2.2 到 channel管理 > Pipeline > 同步进度 菜单下,删除【position 状态】
2.3 编辑下canal的【位点自定义设置】,保存
2.4 重新启动channel。

后记:

问题:
1.canal elapsed 92450 seconds no data
node 停了,要去node/bin/stop.sh node/bin/startup.sh 重启下。

2.Problem accessing /channel_list.htm. Reason:

Failed to invoke Valve[#2/3, level 3]: com.alibaba.citrus.turbine.pipeline.valve.PerformTemplateScreenValve#4f3356c0:PerformTemplateScreenValve
可能是与node有关。清掉node数据重新添加。

3.pipeline 超长延时:
可能是因为源库里的SQL语句有错误造成。(这次是找出哪个库导致的,直接把库重新导入了。)

A:故障;node未找到.

原因:node机器添加完成后,跳转到机器列表页面,获取对应的机器序号nid,node节点对应的唯一标示

B:故障:Unsupported BinlogFormat MIXED
show variables like ‘%log%’;后binlog_format值仍为MIXED
原因;my.cnf下有多余binlog_format赋值MIXED

C:故障:channel挂起,从库未同步主库表数据。(解决方案同DDL语句不能执行故障Exception: no support ddl for)
解决方案;在otter的管理界面,点击同步管理,停用Channel,点击进入Pipeline==>管理=>最下面高级=>跳过ddl异常。重启就OK了

 

坑:

  1. otter CanalParseException: parse row data failed.
    最新canal版本已解决,但是不是稳定版,建议otter降级处理。
    4.2.15 必现~
    https://github.com/alibaba/otter/issues/441
发表在 mysql | 标签为 , , | 留下评论

网易博客日志列表文件转RSS格式

杯具了!

用PHP将网易导出XML转RSS。

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
<?php
// 网易博客日志列表文件转RSS格式。
$src = '网易博客日志列表.xml';
$dst = 'dst.xml';

echo 'loading...', "\r\n";
$dom = new DOMDocument('1.0', 'utf8');
$dom->formatOutput = true;
$rss = $dom->createElement('rss');
$dom->appendChild($rss);
$channel = $dom->createElement('channel');
$rss->appendChild($channel);
$channel->appendChild($dom->createElement('title', '网易博客日志'));
$channel->appendChild($dom->createElement('link', 'http://blog.163.com'));
$channel->appendChild($dom->createElement('description', '网易博客日志列表'));

$doc = simplexml_load_file($src);
$blogs = $doc->children();
foreach($blogs as $blog){
$article = $dom->createElement('item');
$channel->appendChild($article);

$items = get_object_vars($blog);
foreach($items as $key=>$value){
switch($key){
case 'title':
$title = $dom->createElement('title');
$title->appendChild($dom->createCDATASection($value));
$article->appendChild($title);
break;
case 'className':
$class_name = $dom->createElement('title');
$class_name->appendChild($dom->createCDATASection($value));
$article->appendChild($class_name);
break;
case 'content':
$description = $dom->createElement('description');
$description->appendChild($dom->createCDATASection($value));
$article->appendChild($description);
break;
case 'publishTime':
$pubDate = $dom->createElement('pubDate', date(DATE_RSS, substr($value, 0, 10)));
$article->appendChild($pubDate);
break;
}
}
}

$dom->save($dst);
echo 'ok.', "\r\n";

 

下载:163blog_xml_to_rss

发表在 PHP | 标签为 | 留下评论

MySql 清理binlog

今天发现查询执行被卡住,发现是磁盘被binlog占满了,遂清理之。
purge binary logs to ‘master-binlog.000001’;
purge binary logs to ‘master-binlog.000002’;
purge binary logs to ‘master-binlog.000003’;
purge binary logs to ‘master-binlog.000004’;
……
show binary logs;
执行的时候,执行失败(因为磁盘满了,无法写入记录,会被卡住)。
使用:echo ”>最老的一个binlog文件,清空一个binlog文件给腾出点空间。
然后再执行清理语句,mysql查询恢复正常。
发表在 mysql | 标签为 , | 留下评论

输入帐号/密码进入Win服务器上的共享目录

net use \\win-server\tmp /del
net use \\win-server\tmp *  /user:win-server\user1 /persistent:yes

start \\win-server\tmp
——————————————————————————————————————-

在运行中输入“\\”+IP或者计算机名。都可以直接访问共享。
cmd访问方法:
c:\>net use \\192.168.1.1 123 /user:abc
192.168.1.1是服务器的IP。123是密码。abc是用户名。这条命令是登录服务器用的
c:\>net view \\192.168.1.1
这条命令是用来查看共享的

清除共享访问用户名和密码的方法:
打开cmd.
c:\>net use * /del
就可以直接清除所有的共享连接和密码

发表在 windows | 标签为 | 留下评论

MySql 事务死锁及处理

1。定位死锁事务进程:
select trx_mysql_thread_id from information_schema.innodb_trx WHERE trx_state=’RUNNING’;
trx_mysql_thread_id 字段即为事务进程的ID。
2。找出引起事务死锁的进程:
select HOST from information_schema.processlist WHERE id=trx_mysql_thread_id;
host 即其它应用与MySql建立链接的IP和端口号
3。根据端口找出造成死锁的应用:
netstat -nlatp |grep 端口号
tcp        0      0 10.10.20.11:55658       10.10.20.13:3306        ESTABLISHED 进程ID/进程名
4。根据进程ID找出进程:
ps aux|grep 进程ID
www      进程ID  0.0  0.3 272016 28596 ?        S    5月24   0:16 /usr/local/php/php-7.0.18/bin/php
解决,两种方式取其一:
1。找到应用进程,杀死应用进程:
Kill 进程ID
2。找到事物进程,直接杀死MySql的事务进程:
KILL trx_mysql_thread_id;
发表在 mysql | 标签为 , | 留下评论

zephir 开发PHP扩展

占位

发表在 PHP | 标签为 | 留下评论

PHP实现无SMTP服务器发送邮件

前提:

发件人不能用sina.com/qq.com这些,如: 123@sina.com/345@qq.com。只要域名不在未信任名单就好。
QQ邮箱收件人必须是存在的QQ帐号,如:11111111@qq.com
windows必须是php5.3+

define('CF', "\r\n");

$from = rand(22222222, 88888888).'@kindle.com';
$to = 'xxxx@126.com';
$subject = '邮件标题';
$body = '邮件内容';

list($reciver, $host) = explode('@', $to);
list($sender, $local) = explode('@', $from);
$message = array(
'HELO '.$local,
'MAIL FROM: <'.$from.'>',
'RCPT TO: <'.$to.'>',
'DATA',
'MIME-Version: 1.0 '.CF.
'Content-Type: text/plain;charset=utf-8'.CF.
'Content-Transfer-Encoding: base64'.CF.
'From: <'.$from.'>'.CF.
'To: <'.$to.'>'.CF.
'Subject:=?utf-8?B?'.base64_encode($subject).'?='.CF.
CF.
base64_encode($body).CF.
'.'.CF,
'QUIT'
);

$mx = array();
$weight = array();
getmxrr($host, $mx, $weight);
$host = array_shift($mx);

$logs = array();
$fp = fsockopen($host, 25, $errno, $error);
if($fp){
$logs[] = fgets($fp);
foreach($message as $cmd){
$cmd .= "\r\n";
fwrite($fp, $cmd);
$reply = fread($fp, 515);

$logs[] = $cmd;
$logs[] = $reply;

echo 'C:'.$cmd, 'R:'.$reply, "\r\n";
}

fclose($fp);
}

发表在 PHP | 标签为 , | 留下评论