Mdrill集群安装
mdrill是阿里妈妈-adhoc-海量数据多维自助即席查询平台下的一个子项目。旨在帮助用户在几秒到几十秒的时间内,分析百亿级别的任意维度组合的数据。mdrill是一个分布式的在线分析查询系统,基于hadoop,lucene,solr,jstorm等开源系统作为实现,基于SQL的查询语法。
准备阶段
软件准备:
- jdk1.6.0_45.tar.gz
- hadoop-0.20.2-cdh3u3.tar.gz
- alimama-adhoc.tar.gz
- jzmq-2.1.0-1.el6.x86_64.rpm
- zeromq-2.1.7-1.el6.x86_64.rpm
- zookeeper-3.4.5.tar.gz
服务器准备:
如果是线上服务器,建议配置如下:
- 机器数量:10~12台
- CPU:E5-2630(6核)*2
- 内存:>=48GB
- 硬盘规格数量:>=480GB*12 (SSD最佳,普通磁盘也可)。
本次安装采用的是线下私有云- 服务器三台(CentOS-6.6-x86_64)
- 内存 8G
基础环境配置
升级系统
yum update
安装lrzsz
lrzsz是一个可以搭配Xshell和SecureCRT能方便的在本地PC机和远程服务器之间传输文件的小工具。yum install lrzsz -y
关闭IPV6
vi /etc/sysctl.conf
在文件的末尾追加:
1
2
3
4
|
<span class="hljs-id">#disable</span> ipv6
net<span class="hljs-class">.ipv6</span><span class="hljs-class">.conf</span><span class="hljs-class">.all</span><span class="hljs-class">.disable_ipv6</span>=<span class="hljs-number">1</span>
net<span class="hljs-class">.ipv6</span><span class="hljs-class">.conf</span><span class="hljs-class">.default</span><span class="hljs-class">.disable_ipv6</span>=<span class="hljs-number">1</span>
net<span class="hljs-class">.ipv6</span><span class="hljs-class">.conf</span><span class="hljs-class">.lo</span><span class="hljs-class">.disable_ipv6</span>=<span class="hljs-number">1</span>
|
完成后刷新配置 :
sysctl -p
关闭防火墙
setenforce 0 #临时禁用,不需要重启
iptables -F #清空iptables
vi /etc/sysconfig/selinux #修改SELINUX=disabled
chkconfig iptables off && chkconfig ip6tables off #重启后永久失效
修改及设置host
修改hosts文件:vi /etc/hosts
追加如下内容:(注意 这里使用的是局域网IP,在私有云上部署时要特别留意)
1
2
3
|
192.168.113.90 mdrill01
192.168.113.88 mdrill02
192.168.113.101 mdrill03
|
修改每台主机上的配置(注意 hostname要与对应IP地址的主机对应)
vi /etc/sysconfig/network
设置如下内容:
1
|
<span class="hljs-attribute">HOSTNAME</span>=<span class="hljs-string">mdrill01</span>
|
为了让hostname快速生效,避免重启,直接在命令行中设置
hostname mdrill01
设置时间同步
设置时区为本地时间(每台主机都需要执行)cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
选择一台主机为始终同步服务器:这里选择的是mdrill01进行安装yum install ntp -y
安装完成后,修改配置文件:vi /etc/ntp.conf
将配置文件修改为:
1
2
3
4
|
<span class="hljs-title">restrict</span> default nomodify
restrict <span class="hljs-number">192.168.150.0</span> mask <span class="hljs-number">255.255.255.0</span> nomodify notrap
server <span class="hljs-number">127.127.1.0</span>
fudge <span class="hljs-number">127.127.1.0</span> stratum <span class="hljs-number">10</span>
|
启动ntp:
service ntpd start
设置为开机自启
chkconfig ntpd on
同步服务器设置完毕,切换到mdrill02和mdrill03服务器,进行如下操作
yum install ntpdate -y
并设置为每小时同步一次时间:
vim /etc/crontab
新增如下内容:
1
|
1 <span class="hljs-keyword">*</span> <span class="hljs-keyword">*</span> <span class="hljs-keyword">*</span> <span class="hljs-keyword">*</span> root ntpdate h1.hadoop && hwclock -w
|
新增账号
服务器在使用时不建议使用root账户,在这里我们为每台主机添加mdrill账户groupadd mdrill
useradd -g mdrill mdrill
passwd mdrill
创建/data目录,并赋予权限mkdir /data
chown -R mdrill:mdrill /data
设置SSH免密码登陆
每台机器全部切换成mdrill用户su mdrill
在每天机器上执行如下操作(一路回车即可)ssh-keygen -t rsa -P ''
mdrill01执行如下操作cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
scp ~/.ssh/authorized_keys mdrill@mdrill02:~/.ssh/authorized_keys
mdrill02执行如下操作cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
scp ~/.ssh/authorized_keys mdrill@mdrill03:~/.ssh/authorized_keys
mdrill02执行如下操作cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
scp ~/.ssh/authorized_keys mdrill@mdrill01:~/.ssh/authorized_keys
scp ~/.ssh/authorized_keys mdrill@mdrill02:~/.ssh/authorized_keys
完成后再登录每条主机执行chmod 400 ~/.ssh/authorized_keys
至此,免账号登陆就已经打通了
安装阶段
上传准备好的文件
将准备好的文件全部上传到/data目录
- jdk1.6.0_45.tar.gz
- hadoop-0.20.2-cdh3u3.tar.gz
- alimama-adhoc.tar.gz
- jzmq-2.1.0-1.el6.x86_64.rpm
- zeromq-2.1.7-1.el6.x86_64.rpm
安装相应的应用
- 安装jzmq和zeromq
由于是rpm包,所以需要转换到root账号安装,cd data
yum localinstall zeromq-2.1.7-1.el6.x86_64.rpm jzmq-2.1.0-1.el6.x86_64.rpm
rm /data/*.rpm
su mdrill
以上操作需要在3台主机上分别执行
以下操作仅需在1台主机上执行,等最后完成后同步到其他两台机器即可 - 安装jdk
直接解压压缩包tar zxvf jdk1.6.0_45.tar.gz
- 安装hadoop
直接解压压缩包tar zxvf hadoop-0.20.2-cdh3u3.tar.gz
- 安装zookeeper
直接解压压缩包tar zxvf zookeeper-3.4.5.tar.gz
- 安装mdrill
直接解压压缩包tar zxvf alimama-adhoc.tar.gz
由于mdrill默认的使用的是hadoop-0.20.2,所以需要做下调整cp /data/hadoop-0.20.2-cdh3u3/hadoop-core-0.20.2-cdh3u3.jar /data/alimama/adhoc-core/lib/
cp /data/hadoop-0.20.2-cdh3u3/lib/guava-r09-jarjar.jar /data/alimama/adhoc-core/lib/
rm /data/alimama/adhoc-core/lib/hadoop-core-0.20.2.jar
- 清理安装包
rm /data/*.tar.gz
配置环境变量
编辑用户配置文件vi ~/.bashrc
在文件中追加如下内容
1
2
3
4
5
6
7
8
9
10
11
12
|
JAVA_HOME=/data/jdk1.<span class="hljs-number">6.0</span>_45
<span class="hljs-built_in">export</span> JAVA_HOME
PATH=<span class="mathjax-replacement"><span class="hljs-variable">$PATH</span>:<span class="hljs-variable">$</span></span><span class="hljs-variable">JAVA_HOME</span>/bin
<span class="hljs-built_in">export</span> PATH
HADOOP_HOME=/data/hadoop-<span class="hljs-number">0.20</span>.<span class="hljs-number">2</span>-cdh3u3
PATH=<span class="mathjax-replacement"><span class="hljs-variable">$PATH</span>:<span class="hljs-variable">$</span></span><span class="hljs-variable">HADOOP_HOME</span>/bin
<span class="hljs-built_in">export</span> PATH
ZOOKEEPER_HOME=/data/zookeeper-<span class="hljs-number">3.4</span>.<span class="hljs-number">5</span>
PATH=<span class="mathjax-replacement"><span class="hljs-variable">$PATH</span>:<span class="hljs-variable">$</span></span><span class="hljs-variable">ZOOKEEPER_HOME</span>/bin
<span class="hljs-built_in">export</span> PATH
|
先将此文件拷贝到另外两台主机上
scp .bashrc mdrill@mdrill02:~/
scp .bashrc mdrill@mdrill03:~/
为了让环境变量生效,需要每台主机上执行
source ~/.bashrc
修改配置文件
修改hadoop配置文件
cd /data/hadoop-0.20.2-cdh3u3/conf/
vi masters
1
|
mdrill01
|
vi slaves
1
2
|
<span class="hljs-title">mdrill02</span>
mdrill03
|
vi core-site.xml
1
2
3
4
5
6
7
8
9
10
11
12
|
<span class="hljs-pi"><?xml version="1.0"?></span>
<span class="hljs-pi"><?xml-stylesheet type="text/xsl" href="configuration.xsl"?></span>
<span class="hljs-tag"><<span class="hljs-title">configuration</span>></span>
<span class="hljs-tag"><<span class="hljs-title">property</span>></span>
<span class="hljs-tag"><<span class="hljs-title">name</span>></span>hadoop.tmp.dir<span class="hljs-tag"></<span class="hljs-title">name</span>></span>
<span class="hljs-tag"><<span class="hljs-title">value</span>></span>/data/tmp<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
<span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"><<span class="hljs-title">property</span>></span>
<span class="hljs-tag"><<span class="hljs-title">name</span>></span>fs.default.name<span class="hljs-tag"></<span class="hljs-title">name</span>></span>
<span class="hljs-tag"><<span class="hljs-title">value</span>></span>hdfs://mdrill01:9000<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
<span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"></<span class="hljs-title">configuration</span>></span>
|
vi hdfs-site.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<span class="hljs-pi"><?xml version="1.0"?></span>
<span class="hljs-pi"><?xml-stylesheet type="text/xsl" href="configuration.xsl"?></span>
<span class="hljs-tag"><<span class="hljs-title">configuration</span>></span>
<span class="hljs-tag"><<span class="hljs-title">property</span>></span>
<span class="hljs-tag"><<span class="hljs-title">name</span>></span>dfs.replication<span class="hljs-tag"></<span class="hljs-title">name</span>></span>
<span class="hljs-tag"><<span class="hljs-title">value</span>></span>1<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
<span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"><<span class="hljs-title">property</span>></span>
<span class="hljs-tag"><<span class="hljs-title">name</span>></span>dfs.name.dir<span class="hljs-tag"></<span class="hljs-title">name</span>></span>
<span class="hljs-tag"><<span class="hljs-title">value</span>></span>/data/dfs/name<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
<span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"><<span class="hljs-title">property</span>></span>
<span class="hljs-tag"><<span class="hljs-title">name</span>></span>dfs.data.dir<span class="hljs-tag"></<span class="hljs-title">name</span>></span>
<span class="hljs-tag"><<span class="hljs-title">value</span>></span>/data/dfs/data<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
<span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"></<span class="hljs-title">configuration</span>></span>
|
vi mapred-site.xml
1
2
3
4
5
6
7
8
|
<span class="hljs-pi"><?xml version="1.0"?></span>
<span class="hljs-pi"><?xml-stylesheet type="text/xsl" href="configuration.xsl"?></span>
<span class="hljs-tag"><<span class="hljs-title">configuration</span>></span>
<span class="hljs-tag"><<span class="hljs-title">property</span>></span>
<span class="hljs-tag"><<span class="hljs-title">name</span>></span>mapred.job.tracker<span class="hljs-tag"></<span class="hljs-title">name</span>></span>
<span class="hljs-tag"><<span class="hljs-title">value</span>></span>http://mdrill01:9001<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
<span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"></<span class="hljs-title">configuration</span>></span>
|
在完成上述配置后,需要创建相应的目录
mkdir /data/tmp
mkdir -p /data/dfs/name
mkdir -p /data/dfs/data
修改zookeeper配置文件
vi /data/zookeeper-3.4.5/conf/zoo.cfg
更新如下内容:
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
|
<span class="hljs-comment"># The number of milliseconds of each tick</span>
<span class="hljs-constant">tickTime</span>=2000
<span class="hljs-comment"># The number of ticks that the initial </span>
<span class="hljs-comment"># synchronization phase can take</span>
<span class="hljs-constant">initLimit</span>=10
<span class="hljs-comment"># The number of ticks that can pass between </span>
<span class="hljs-comment"># sending a request and getting an acknowledgement</span>
<span class="hljs-constant">syncLimit</span>=5
<span class="hljs-comment"># the directory where the snapshot is stored.</span>
<span class="hljs-comment"># do not use /tmp for storage, /tmp here is just </span>
<span class="hljs-comment"># example sakes.</span>
<span class="hljs-constant">dataDir</span>=/data/zookeeper-3.4.5/data
<span class="hljs-comment"># the port at which the clients will connect</span>
<span class="hljs-constant">clientPort</span>=2181
<span class="hljs-comment">#</span>
<span class="hljs-comment"># Be sure to read the maintenance section of the </span>
<span class="hljs-comment"># administrator guide before turning on autopurge.</span>
<span class="hljs-comment">#</span>
<span class="hljs-comment"># http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance</span>
<span class="hljs-comment">#</span>
<span class="hljs-comment"># The number of snapshots to retain in dataDir</span>
<span class="hljs-comment">#autopurge.snapRetainCount=5</span>
<span class="hljs-comment"># Purge task interval in hours</span>
<span class="hljs-comment"># Set to "0" to disable auto purge feature</span>
<span class="hljs-comment">#autopurge.purgeInterval=1</span>
<span class="hljs-constant">maxClientCnxns</span>=300
<span class="hljs-constant">maxSessionTimeout</span>=20000
server.1=mdrill101:2888:3888
server.2=mdrill102:2888:3888
server.3=mdrill103:2888:3888
|
创建相应的目录,并写入zookeeperid
mkdir /data/zookeeper-3.4.5/data
vi /data/zookeeper-3.4.5/data/myid
写入数字1即可
1
|
1
|
修改mdrill配置文件
vi /data/alimama/adhoc-core/conf/storm.yaml
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
|
####zookeeper配置####
storm.zookeeper.<span class="hljs-string">servers:</span>
- <span class="hljs-string">"mdrill01"</span>
- <span class="hljs-string">"mdrill02"</span>
- <span class="hljs-string">"mdrill03"</span>
storm.zookeeper.<span class="hljs-string">port:</span> <span class="hljs-number">2181</span>
storm.zookeeper.<span class="hljs-string">root:</span> <span class="hljs-string">"/higo2"</span>
####蓝鲸配置####
storm.local.<span class="hljs-string">dir:</span> <span class="hljs-string">"/data/alimama/bluewhale/stormwork"</span>
nimbus.<span class="hljs-string">host:</span> <span class="hljs-string">"mdrill162"</span>
####hadoop配置####
hadoop.conf.<span class="hljs-string">dir:</span> <span class="hljs-string">"/data/hadoop-0.20.2-cdh3u3/conf"</span>
hadoop.java.<span class="hljs-string">opts:</span> <span class="hljs-string">"-Xmx1536m"</span>
####蓝鲸各种心跳间隔配置####
nimbus.task.timeout.<span class="hljs-string">secs:</span> <span class="hljs-number">240</span>
task.heartbeat.frequency.<span class="hljs-string">secs:</span> <span class="hljs-number">12</span>
nimbus.supervisor.timeout.<span class="hljs-string">secs:</span> <span class="hljs-number">360</span>
supervisor.heartbeat.frequency.<span class="hljs-string">secs:</span> <span class="hljs-number">10</span>
nimbus.monitor.freq.<span class="hljs-string">secs:</span> <span class="hljs-number">20</span>
supervisor.worker.timeout.<span class="hljs-string">secs:</span> <span class="hljs-number">240</span>
supervisor.monitor.frequency.<span class="hljs-string">secs:</span> <span class="hljs-number">12</span>
worker.heartbeat.frequency.<span class="hljs-string">secs:</span> <span class="hljs-number">4</span>
storm.zookeeper.session.<span class="hljs-string">timeout:</span> <span class="hljs-number">60000</span>
storm.zookeeper.retry.<span class="hljs-string">interval:</span> <span class="hljs-number">6000</span>
storm.zookeeper.retry.<span class="hljs-string">times:</span> <span class="hljs-number">10</span>
####mdrill配置####
higo.workdir.<span class="hljs-string">list:</span> <span class="hljs-string">"/data/alimama/higoworkerdir"</span>
#----mdrill的表格列表在hdfs下的路径-----
higo.table.<span class="hljs-string">path:</span> <span class="hljs-string">"/mdrill/tablelist"</span>
#----mdrill中启动的solr使用的初始端口号-----
higo.solr.ports.<span class="hljs-string">begin:</span> <span class="hljs-number">51110</span>
#----mdrill分区方式,目前支持<span class="hljs-keyword">default</span>,day,month,single,<span class="hljs-keyword">default</span>是将一个月分成<span class="hljs-number">3</span>个区,single意味着没有分区-----
higo.partion.<span class="hljs-string">type:</span> <span class="hljs-string">"day"</span>
#----每台机器启动的worker进程端口列表----
supervisor.slots.<span class="hljs-string">ports:</span>
- <span class="hljs-number">6701</span>
- <span class="hljs-number">6702</span>
- <span class="hljs-number">6703</span>
- <span class="hljs-number">6704</span>
- <span class="hljs-number">6705</span>
- <span class="hljs-number">6706</span>
- <span class="hljs-number">6707</span>
- <span class="hljs-number">6708</span>
- <span class="hljs-number">6709</span>
- <span class="hljs-number">6710</span>
- <span class="hljs-number">6711</span>
- <span class="hljs-number">6712</span>
- <span class="hljs-number">6713</span>
- <span class="hljs-number">6714</span>
- <span class="hljs-number">6601</span>
#----创建索引生成的每个shard的并行----
higo.index.<span class="hljs-string">parallel:</span> <span class="hljs-number">3</span>
#----启动的shard的数,每个shard为一个solr实例,结合cpu个数和内存进行配置,<span class="hljs-number">10</span>台<span class="hljs-number">48</span>G内存配置<span class="hljs-number">60</span>----
higo.shards.<span class="hljs-string">count:</span> <span class="hljs-number">30</span>
#----基于冗余的ha,设置为<span class="hljs-number">1</span>表示没有冗余,如果设置为<span class="hljs-number">2</span>,则冗余号位<span class="hljs-number">0</span>,<span class="hljs-number">1</span>----
higo.shards.<span class="hljs-string">replication:</span> <span class="hljs-number">1</span>
#----启动的merger server的worker数量,建议根据机器数量设定----
higo.mergeServer.<span class="hljs-string">count:</span> <span class="hljs-number">5</span>
#----分配给merger server的端口,建议每台机器分配一个merger server----
higo.merge.<span class="hljs-string">ports:</span> <span class="hljs-string">"6601,6602,6603,6604,6605"</span>
#----mdrill同时最多加载的分区个数,取决于内存与数据量----
higo.cache.<span class="hljs-string">partions:</span> <span class="hljs-number">10</span>
#----通用的worker的jvm参数配置----
worker.<span class="hljs-string">childopts:</span> <span class="hljs-string">"-Xms4g -Xmx4g -Xmn2g -XX:SurvivorRatio=3 -XX:PermSize=96m -XX:MaxPermSize=256m -XX:+UseParallelGC -XX:ParallelGCThreads=16 -XX:+UseAdaptiveSizePolicy -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:%storm.home%/logs/gc-%port%.log "</span>
|
线上服务器配置建议:每台机器上配置6个shard,1个merger server,均分配5GB的内存
创建配置文件中涉及到的目录mkdir -p /data/alimama/bluewhale/stormwork
mkdir -p /data/alimama/higoworkerdir
同步所有内容到各台主机
scp -r /data mdrill@mdrill02:/
scp -r /data mdrill@mdrill02:/
由于是同步过去,所以 zookeeper的myid需要在另外两台主机上设置
在mdrill02主机上vi /data/zookeeper-3.4.5/data/myid
1
|
2
|
再mdrill03主机上
vi /data/zookeeper-3.4.5/data/myid
1
|
3
|
启动服务器
启动Hadoop
在启动hadoop前需要先对namenode进行格式化hadoop namenode -format
由于设置了环境变量,启动起来非常简单start-all.sh
只要在主节点执行上诉内容,其他两台机器相关的进程会一并启动
如需停止,可运行如下命令stop-all.sh
相关端口:
- jobtracker:50030
- tasktracker:50060
启动zookeeper
在每天主机上执行如下命令即可zkServer.sh start
如需停止zkServer.sh stop
如需查看状态zkServer.sh status
启动mdrill
cd /data/alimama/adhoc-core/bin/
chmod 777 ./bluewhale
nimbus是整个mdrill集群任务的总调度,有点类似hadoop的jobtracker
只需要在其中一台机器启动即可,启动命令如下nohup ./bluewhale nimbus > nimbus.log &
supervisor用来管理其所在机器的work进程,其角色有点类似hadoop的tasktracker
需要在每台机器上启动,nohup ./bluewhale supervisor > supervisor.log &
视情况看是否需要启动mdrilluimkdir ./ui
nohup ./bluewhale mdrillui 1107 ../lib/adhoc-web-0.18-beta.war ./ui >ui.log &
启动后,可以通过浏览器打开对应ip的1107端口,看是否能正常打开即可。
测试mdrill
建表
将建表SQL存储为create.sql到“/data/alimama/adhoc-core/bin/”目录下,
1
2
3
4
5
6
|
<span class="hljs-operator"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> st(
thedate <span class="hljs-keyword">string</span>,
c1 <span class="hljs-keyword">string</span>,
c2 tdouble,
cnt tlong
)</span>
|
执行如下命令
cd /data/alimama/adhoc-core/bin/
./bluewhale mdrill create ./create.sql
列的数据类型目前只支持4种
- string :字符串类型
- tlong :long整形
- tdouble :浮点型
- tdate :日期类型
- text:字符串类型(进行了分词,意味着只能进行全文检索,而不能参与统计与分组)
另外如果数据类型用_mdrill_进行了分割,后面的值表示是否存储,在全文检索模式中特别有用,全文检索模式要把要进行展示的列配置成存储(速度能提升很多)
举例如下
下面这几个为只索引而不存储数据的值
1
2
3
4
5
|
string_mdrill_<span class="hljs-literal">false</span>
tlong_mdrill_<span class="hljs-literal">false</span>
tdouble_mdrill_<span class="hljs-literal">false</span>
tdate_mdrill_<span class="hljs-literal">false</span>
text_mdrill_<span class="hljs-literal">false</span>
|
下面这几个为只既索引也存储数据的值
1
2
3
4
5
|
string_mdrill_<span class="hljs-literal">true</span>
tlong_mdrill_<span class="hljs-literal">true</span>
tdouble_mdrill_<span class="hljs-literal">true</span>
tdate_mdrill_<span class="hljs-literal">true</span>
text_mdrill_<span class="hljs-literal">true</span>
|
另外如果要跳过某些列,可以将数据类型配置成ignored,表示这个列既不存储也不索引。
注意
- 建表语句要与数据存储顺序一致
- thedate:是分区的字段,必须存在,格式为yyyyMMdd格式的字符串,且要与对应的分区目录要对应
其他信息
如果需要经常的进行全文检索,那么可以配置成存储明细,使用额外的存储,换取全文检索的时间./bluewhale mdrill create ./create.sql true
导入离线数据
数据目录
首先要确定数据表在hdfs上的根目录,比如说/mdrill/tablelist。目录在/data/alimama/adhoc-core/conf/storm.yaml的mdrill配置文件配置。
在该目录下可以有一个至多个数据表,每个数据表目录下会有三个子目录。
- solr:表的配置目录
- index:mdrill的索引在hdfs中的存储路径
- tmp:临时目录
数据格式
- mdrill默认处理的是sequencefile格式的数据,对key没有要求,value则为对应数据表中一条记录,记录的列与列之间的分隔符为默认 01,如果使用文本格式的,或者分隔符不是 01,创建索引逻辑时要注意传递的参数。
- mdrill要求数据按照天进行分目录,目录命名必须为dt=yyyyMMdd这种格式
- 数据的列中必须含有一列叫thedate,其值与其所在的目录dt=yyyyMMdd中的yyyyMMdd相等,thedate实际上为mdrill的分区字段,任何的查询都必须指定thedate分区。如果数据列中的thedate与目录中的dt=yyyyMMdd不相等,那么mdrill以目录的时间为准确时间。
- mdrill默认必须按照日期分区,使用分区后总存储的数据量会显著提升,每天创建的索引也是增量的,如果确实因为某种原因无法按照日期分区,可以将分区类型设置为single,但是总的数据存储量会减少很多。
生存索引
指令规则:./bluewhale mdrill index {表名}{hdfs源数据地址} 3650 {起始日期} {数据格式seq|txt,不写默认seq} {分隔符,不写默认 01} {分区下的文件匹配规则默认匹配*0* }
指令示例:./bluewhale mdrill index st /mdrill/tablelist/st 3650 20140101 txt
./bluewhale mdrill index st /mdrill/tablelist/st 3650 20140101 txt tab "\*\*" 3 1
启动表
启动表指令./bluewhale mdrill table {表1,表2,表3}
示例:./bluewhale mdrill table st
停止表指令./bluewhale mdrill drop {表1,表2,表3}
示例:./bluewhale mdrill drop st
注意
启动表的操作只能执行一次,如果想添加新的表必须先停止表后再启动表。
重启服务
如果是因为mdrill本身的bug,需要重启mdrill,则可以这样做
- 先停止表
- 在每台机器上杀死所有的mdrill任务
ps -x|grep bluewhale|grep server|awk '{printf("%s ",$1)}'|xargs kill
- 清理mdrill的临时目录
rm /data/alimama/bluewhale/stormwork/* -rf
- 重新按照原先的步骤 启动mdrill
- 启动表
配置实时数据源(如果使用离线模式,请跳过此步)
编辑storm.yaml配置文件,假设要配置为实时的表的名字为p4p_v2
- 配置editlog记录的位置,可以选择为local或hdfs
hdfs模式没有经过严格的测试,如果hadoop集群不是经常的停机维护或者出问题,那么可以考虑使用hdfs模式,这样因为机器宕机或者硬盘损坏导致的数据丢失损失会减少到最小
local模式表示editlog会记录到本地的硬盘上,如果这台机器硬件损坏或者宕机,那么那些还没有同步到hdfs中的索引数据会丢失(默认同步间隔为4小时,配置目前为硬编码,请参考com.alimama.mdrill.utils.UniqConfig里面的设置)higo.realtime.binlog: "local"
- 需要先将表配置为实时模式,配置方法如下
higo.mode.p4p_pv2: "@realtime@"
- 配置表的分区:可以为day,month,default
higo.partion.type.p4p_pv2: "day"
- 配置日志解析类
解析类需要实现com.alimama.mdrillImport.DataParser接口,示例程序如下p4p_pv2-parse: "com.alimama.quanjingmonitor.mdrillImport.parse.p4p_pv2"
- 配置reader
reader用于实时的读取数据,然后交给解析类解析后导入到mdrill里
reader在阿里可以使用tt4(默认已经实现),阿里外部可以考虑使用metaq或者kafka
需要实现的接口为com.alimama.mdrillImport.ImportReader.RawDataReader
TT4实现的示例为com.alimama.quanjingmonitor.mdrillImport.reader.TT4Reader
- 配置导入模式为local与merger
数据导入到mdrill前,如果数据可以进行简单的合并,那么会大量的减少导入到mdrill里的数据量,合并的方式很简单就是按照解析类的getGroup方法进行分组,getSum里的值进行累加而已,如果我们的数据很难进行合并,则建议使用local模式以减少没必要的传输,如果合并比率很高,那么建议使用mergerp4p_pv2-mode: "local"
- 配置各种缓存参数
p4p_pv2-commitbatch: 5000 //单次向mdrill递交的记录数
p4p_pv2-commitbuffer: 10000//commit阶段的buffer长度
p4p_pv2-spoutbuffer: 10000//spout阶段的buffer长度
p4p_pv2-boltbuffer: 10000 //bolt阶段的buffer长度
- 配置缓存的刷新时间:与解析类的getTs()方法组合使用
p4p_pv2-timeoutSpout: 240 //配置在spout的最大缓存时间
p4p_pv2-timeoutBolt: 60 //配置在bolt里的最大缓存时间
p4p_pv2-timeoutCommit: 30 //配置在commit阶段的最大缓存时间
导入实时数据
导入指令./bluewhale jar ./mdrill.jar com.alimama.mdrillImport.Topology {自定义任务名称} {导入的表列表多个表之间用逗号分隔} {使用的进程总数} {每个进程使用多少mb的内存} {从什么时间开始导入}
示例如下./bluewhale jar ./mdrill.jar com.alimama.quanjingmonitor.mdrillImport.Topology p4p_pv2topology p4p_pv2 66 512 20131231074710
如果想停止导入数据的程序./bluewhale kill {自定义的任务名称}
示例如下./bluewhale kill p4p_pv2topology
测试mdrill查询
mdrill的分区
mdrill的设计默认是使用分区的,也是按照分区进行存储的,除非强制使用single类型的分区外,查询的时候必须指定分区。目前mdrill的分区字段为thedate,格式为yyyyMMdd
在顶层SQL的where条件中必须有如下三种分区设定的一种
- thedate=’yyyyMMdd’ 直接指定某一个分区
- thedate in (yyyyMMdd, yyyyMMdd, yyyyMMdd) 给出一系列日期
- thedate >= yyyyMMdd and thedate<= thedate 给出一个范围
查询明细
- mdrill可以查询top 10000 条数据的明细,使用limit关键词
- 对于明细的数据,可以进行排序,也就是order by
统计汇总
mdrill目前支持sum,max,min,count,dist五种汇总函数
- dist就是sql中的count(distinct(xxx)),但是采用的是近似计算,会有一定的误差具体实现原理,请参考https://github.com/muyannian/higo/wiki/distinct
- count有两种使用方法
- count(列名),针对具体某一列进行count统计,当然如果该列值如果存在NULL值,不会作为count计数。
- count(*),即使存在NULL的列,也会列入计数。
分类汇总
mdrill目前支持多维分类汇总统计,也就是sql中的group by。另外分类汇总后,mdrill可以按照某一列的值进行排序,如果分类汇总后的组数小于10000组为准确排序,如果超过10000组则为近似的排序和计算,有可能存在排序的顺序和计算的结果不正确的情况。
mdrill的过滤
目前mdrill的过滤支持如下几种
- =:等于
- <>:不等于
- >=:大于等于
- <=:小于等于
- >:大于
- <:小于
- in:属于列表
- not in:属于列表
- like:模糊匹配
mdrill FAQ
数据在内存中是如何存储的
- mdrill是先进行分shard的,每个shard分布在不同的机器的不同的进程中
- 每个shard是按照时间进行分区的,每个分区是一个索引
- 每个索引是按照列进行存储的,每次缓存的时候加载一个列的值到内存中,多个分区,多个表,多个列之间LRU方式淘汰
- 加载到内存中的列,并非是原始值,而是一个值的整形的代号,比方说用一个数字899代替一个很长的字符串
对内存结构的解释
- 将lucene默认的将整个列数据全部都load到内存中的方式修改为load 每个列的值的编码代号,操作的时候也仅仅操作这些代号,真正展现的时候再将这些编号转换成真实的值,编号的数据类型根据某个列的值的重复程度可以为byte,short,int
- 将数据进行分区(默认按照时间),用到的数据会加载到分区中,不用的分区会从内存中踢出,采用LRU的方式管理,如果同时需要检索大量的分区,则进行排队处理,一个分区一个分区的处理。
- 多个表之间也合并,共享内存,用到的表才会加载到内存中,没用到的则在硬盘中存储。
- 原先merger server与shard是在同一个进程中的,每次查询的时候随机使用其中一个shard作为merger server,如果每次查询merger server使用1G的内存,但shard的数量非常多,merger server每次只用一个,但是为每个shard都额外分配1G内存就是浪费,新版mdrill将这两者分开,避免浪费。
- 按照内存大小进行LRU,而不是按照field的个数,不同列因为重复读不同对内存的消耗也不一样,按照个数LRU不合理,按照总内存使用LRU
- 由于每次逆旋都需要消耗时间,当LRU被淘汰的时候,将逆旋的结果保留到硬盘中,以备下次使用。
worker.childopts与 higo.merge.ports有什么区别
merger server只管理合并数据,shard才是资源使用大户,一般一台机器启动一个merger server就够了 ,没必要启动那么多。
- worker.childopts用来标记 这台机器可以启动那些端口
- higo.merge.ports用来标记 这些端口中哪些是merger server的端口
higo.shards.count+higo.mergeServer.count = 启动的总的进程数
- higo.shards.count:表示启动的shard数量,一个shard就是一个存储索引的solr
- higo.mergeServer.count:表示启动的merger server的数量,一个merger server也是一个solr,但是他没有索引,仅仅用于合并shard的数据据