spark-topN问题

业务场景 统计ip

加载hdfs数据文件

统计出现频率前N的ip

Spark实例TopN—Spark学习笔记11

正则表达式基础知识

String 类的 r() 方法构造了一个Regex对象。

然后使用 findFirstIn 方法找到首个匹配项。

如果需要查看所有的匹配项可以使用 findAllIn 方法。

Scala 的正则表达式继承了 Java 的语法规则,Java 则大部分使用了 Perl 语言的规则

可以使用 mkString( ) 方法来连接正则表达式匹配结果的字符串,并可以使用管道(|)来设置不同的模式:

1
2
3
val pattern = "Scala".r
val str = "Scala is Scalable and cool"
println(pattern findFirstIn str)

构造ip正则表达式

对于大量转义字符及换行的字符串可以使用三个双引号
简单的正则表达式
((\d+.){3}\d+)
正则是没有办法做数字运算的,如何表示范围?分析ip地址规律,按不同情况分组再组合
((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))).){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))

IP地址的正则表达式写法

如果内容比较复杂,正则表达式可能会匹配冗余内容

1
2
3
var data = sc.textFile("hdfs://toshiba:9000/user/xiaohei/hadoop/access.20120104.log")
var top50 = data.map(line => """(\d+\.){3}\d+""".r.findFirstIn(line).mkString).filter(_!="").map(word => (word,1)).reduceByKey(_+_).map(word=>(word._2,word._1)).sortByKey(false).map(word=>(word._2,word._1)) take 50
top50.foreach(x => println(x))

利用元组位置

1
2
3
4
5
var data = sc.textFile("hdfs://toshiba:9000/user/xiaohei/hadoop/access.20120104.log")
var top10 = data.map(_.split(" ")).map(line => (line(0),1)).reduceByKey(_+_).map(word => (word._2,word._1)).sortByKey(false).map(word => (word._2,word._1)) take 10
top10.foreach(x => println(x))

代码注解

line(0) 表示元组第一个元素

sortByKey(flase)代表逆序 sortByKey 默认值是sortByKey(true)代表升序

将map的k,v互换,变成(value, IP) 这样才能利用sortByKey排序找出top的IPs

互换两次则回原来的格式

引出问题

如何根据value 进行排序?

1
2
3
sortBy(_._x,flase) # 根据元组的第x字段进行排序
var top20 = data.map(_.split(" ")).map(line => (line(0),1)).reduceByKey(_+_).sortBy(_._2,false) take 20
top20.foreach(x => println(x))

hbase学习笔记

hbase 基本架构

版本选用

  • hadoop 2.7.4
  • hbase 1.2.6

    hadoop hbase版本兼容

hbase 定位

与hadoop对接

1
2
3
4
<property>
<name>hbase.rootdir</name>
<value>hdfs://namenode.example.org:8020/hbase</value>
</property>

与zookeeper对接

hbase 自带的zookeeper

hbase-env.sh

1
2
# Tell HBase whether it should manage its own instance of ZooKeeper or not.
export HBASE_MANAGES_ZK=true

startup

When HBase manages ZooKeeper, it will start/stop the ZooKeeper servers as a part of the regular start/stop scripts. If you would like to run ZooKeeper yourself, independent of HBase start/stop, you would do the following

1
${HBASE_HOME}/bin/hbase-daemons.sh {start,stop} zookeeper

外部的zookeeper

hbase-env.sh

1
2
# Tell HBase whether it should manage its own instance of ZooKeeper or not.
export HBASE_MANAGES_ZK=false

hbase-site.xml

1
2
3
4
5
6
7
8
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>node-a.example.com,node-b.example.com,node-c.example.com</value>
</property>

单机配置与安装

存储在本地文件

1
2
3
4
5
6
7
8
9
10
11
<configuration>
<property>
<name>hbase.rootdir</name>
<value>file:///home/testuser/hbase</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/testuser/zookeeper</value>
</property>
</configuration>

存储在HDFS

1
2
3
4
5
6
7
8
9
10
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://namenode.example.org:8020/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>false</value>
</property>
</configuration>

伪分布式配置与安装

hbase-site.xml

1
2
3
4
5
6
7
8
<property>
<name>hbase.rootdir</name>
<value>hdfs://localhost:8020/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>

分布式安装

Node Name Master ZooKeeper RegionServer
node-a.example.com yes yes no
node-b.example.com backup yes yes
node-c.example.com no yes yes

hbase-site.xml

1
2
3
4
5
6
7
8
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>node-a.example.com,node-b.example.com,node-c.example.com</value>
</property>

conf/regionservers

1
2
3
node-a.example.com
node-b.example.com
node-c.example.com

conf/backup-masters

1
2
node-b.example.com
node-c.example.com

docker容器和镜像管理

docker images往往不知不觉就占满了硬盘空间,为了清理冗余的image,可采用以下方法:

1.进入root权限

sudo su

2.停止所有的container,这样才能够删除其中的images:

1
docker stop $(docker ps -a -q)

如果想要删除所有container的话再加一个指令:

1
docker rm $(docker ps -a -q)

3.查看当前有些什么images

1
docker images

4.删除images,通过image的id来指定删除谁

1
2
docker rmi <image id>

想要删除untagged images,也就是那些id为的image的话可以用

1
2
docker rmi $(docker images | grep "^<none>" | awk "{print $3}")

要删除全部image的话

1
docker rmi $(docker images -q)

docker数据共享

docker 数据共享

方式1

docker之文件夹共享

共享宿主机的目录给容器

1
docker run -d --name=test -v /opt/test:/usr/databases docker-test

test是容器的名字,需唯一;-v表示创建一个数据卷并挂载到容器里,示例表示把宿主机的/opt/test目录挂载到容器的/usr/databases目录下;docker-test是镜像的名字

有时候需要共享容器的volume,则需采用其他方式来访问

采用–volumes-from
可以使用最小的镜像busybox来帮忙实现

1
docker run --name=storedata -v /data/bigdata:/usr/data busybox true

定义一个名称为storedata的目录映射,示例表示把宿主机的/data目录挂载到容器的/usr/data目录下。其他的容器就可以采用–volumes-from来使用该目录

1
2
docker run -d --name=test1 --volumes-from storedata docker-test
docker run -d --name=test2 --volumes-from storedata docker-test

采用ln链接的方式把不同目录挂载到同一个目录下

1
2
ln -s /data /opt/es1/
ln -s /data /opt/es2/

示例在/opt/es1/和/opt/es2/目录下都生成了一个指向/data目录的快捷方式,因此访问/opt/es1/data和/opt/es2/data都是访问的/data目录

搞定了链接,现在就可以直接采用-v来映射目录了

1
2
docker run -d --name=test3 -v /opt/es1/data:/usr/data docker-test
docker run -d --name=test4 -v /opt/es2/data:/usr/data docker-test

这样,在test3和test4容器内部操作/usr/data目录都是操作的宿主机的/data目录

参考链接

  1. docker 文件共享

批量拷贝文件到特定目录

拷贝出当前目录及子目录下面的某类文件

find+exec

1
find ~/ffmpeg -name "*.a" -type f -exec cp {} ./ffmpeg/lib \;

\;是转义分号,不让shell去解释,因为这个分号是给-exec用的.
Linux下用find查找并复制指定文件到指定目录下

find+xargs

1
find . -name '*.ppt' | xargs -i cp {} /path/to

加-i 参数直接用 {}就能代替管道之前的标准输出的内容;

加 -I 参数 需要事先指定替换字符

find 后cp或拷贝目录结构

find

find命令
#
xargs

datanode启动失败

背景:hadoop版本切换

hadoop 版本从2.6.5 切换到了2.7.4

结果datanode 启动失败

日志分析

错误提示namespaceIDs不一致。

解决办法1

删掉hadoop tmp目录下所有数据后,重新格式化

  1. 停掉集群服务
  2. 在出问题的datanode节点上删除data目录,data目录即是在hdfs-site.xml文件中配置的dfs.data.dir目录,本机器上那个是/var/lib/hadoop-0.20/cache/hdfs/dfs/data/ (注:我们当时在所有的datanode和namenode节点上均执行了该步骤。以防删掉后不成功,可以先把data目录保存一个副本).
  3. 格式化namenode.
  4. 重新启动集群。

    原因

    每次namenode format会重新创建一个namenodeId,而tmp/dfs/data下包含了上次format下的id,namenode format清空了namenode下的数据,但是没有晴空datanode下的数据,导致启动时失败,所要做的就是每次fotmat前,清空tmp一下 的所有目录. 

这种方法带来的一个副作用即是,hdfs上的所有数据丢失。如果hdfs上存放有重要数据的时候,不建议采用该方法,可以尝试提供的网址中的第二种方法。

解决办法2

更新有问题的datanode 的namespaceID

  1. 停止datanode
  2. 编辑datanode namespaceID in /current/VERSIO to match the value of the current namenode
  3. 重启datanode
1
2
3
4
5
6
#contents of <dfs.data.dir>/current/VERSION
namespaceID=393514426
storageID=DS-1706792599-10.10.10.1-50010-1204306713481
cTime=1215607609074
storageType=DATA_NODE
layoutVersion=-13

参考资料

  1. HADOOP报错Incompatible namespaceIDs

centos6 安装oracle11g

从centos.min 安装基本组件

配置国内源

1
2
3
4
5
6
7
8
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
cd /etc/yum.repos.d/
curl -o CentOS6-Base-163.repo mirrors.163.com/.help/CentOS6-Base-163.repo
yum clean all
yum makecache
yum install git zsh wget vim openssh-server gcc unzip
yum groupinstall "Desktop" # gnome
yum groupinstall "X Window System"

配置oracle 源 (root)

1
2
3
4
cd /etc/yum.repos.d
wget --no-check-certificate https://public-yum.oracle.com/public-yum-ol6.repo
wget --no-check-certificate https://public-yum.oracle.com/RPM-GPG-KEY-oracle-ol6 -O /etc/pki/rpm-gpg/RPM-GPG-KEY-oracle
yum makecache # 这一步不要执行public-yum-ol6.repo 网速慢

安装oracle

安装依赖

1
2
yum install oracle-rdbms-server-11gR2-preinstall
id oracle #检查oracle用户是否属于oinstall,dba

安装完依赖后,oracle用户,oinstall,dba 用户组已经建好
相关的系统配置文件也已经生成

建文件夹并赋予权限

1
2
3
mkdir -p /u01/app/oracle/product/11.2.0/dbhome_1
chown -R oracle:oinstall /u01
chmod -R 775 /u01

环境变量

先建bash文件里面的环境变量,不然无法安装数据库 $ORACLE_BASE是必须的

1
2
3
4
5
6
7
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/dbhome_1
export ORACLE_SID=ORCL
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORACLE_HOME/network/lib:/lib:/usr/lib:/usr/local/lib
export CLASSPATH=$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib
export PATH=$PATH:$ORACLE_HOME/bin

其他项

检查/etc/host及/etc/hosts文件

要符合域名格式 eg:oracle.centos6.com

/etc/hosts 文件中添加相应的记录

关闭防火墙

1
service iptables stop

中文支持

1
yum groupinstall "Chinese Support"

修改/etc/sysconfig/i18n

LANG="en_US.UTF-8" 改为LANG="zh_CN.UTF-8"

这个可以不改

安装oracle程序包

若中文乱码,执行

1
export LANG="en_US.UTF-8"

docker设置静态ip

docker设置静态ip脚本

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
#/bin/bash
if [ -z $1 ] || [ -z $2 ] || [ -z $3 ] || [ -z $4 ];
then
echo "*****Input the necessary parameters: CONTAINERID IP MASK GATEWAY"
echo "*****Call the script like: sh manual_con_static_ip.sh b0e18b6a4432 192.168.5.123 24 192.168.5.1"
exit
fi
CONTAINERID=$1
SETIP=$2
SETMASK=$3
GATEWAY=$4
pid=`docker inspect -f '{{.State.Pid}}' $CONTAINERID`
mkdir -p /var/run/netns
find -L /var/run/netns -type l -delete
ln -s /proc/$pid/ns/net /var/run/netns/$pid
ip link add A type veth peer name B
brctl addif br0 A
ip link set A up
ip link set B netns $pid
ip netns exec $pid ip link set dev B name eth0
ip netns exec $pid ip link set eth0 up
ip netns exec $pid ip addr add $SETIP/$SETMASK dev eth0
ip netns exec $pid ip route add default via $GATEWAY