大数据对于计算机科学的意义,大致相当于大规模生产对于资本主义发展的意义,在此基础上,才有了工业化和现代化。
如果我们仔细去研究的话,会发现大数据的整个体系和生产制造实在是太像了~
以前本地运行的应用就像是封建时代的手工作坊,随后发展起来的大工业则是基于供应链的。大数据也是一样,诸多中间件正是扮演着供应链的角色。
从大的方面来说,首先是生产模式的问题。随着分工的完善,外包租赁成为主流的生产模式:
I:Infrastructure,设备租赁,产品还是自己生产(比如阿里云服务器租赁)
P:platform,外包生产,自己只提供核心技术完成最后的组装(比如阿里云机器学习平台)
S:Software,代工生产,完全没有开发工作,直接可以用了(比如阿里网上邮件系统)
HDFS是分布式文件系统,相当于一个公司可以在多个地方建立仓库。Alluxio是一个类似HDFS但是基于内存的分布式系统,其速度和吞吐都比HDFS性能要好。
下面简单介绍一下HDFS,HDFS是Hadoop Distribute File System 的简称,也就是Hadoop的一个分布式文件系统。NameNode、SecondaryNameNode负责事务管理,DataNode负责存储和读写数据。默认数据块block大小64MB,每个block复制3份分别放在不同的node上,信息保存在meta-data中(可以用mysql保存)。
fsimage:元数据镜像文件(文件系统的目录树。)
edits:元数据的操作日志(针对文件系统做的修改操作记录)
namenode内存中存储的是=fsimage+edits。
SecondaryNameNode负责定时默认1小时,从namenode上,获取fsimage和edits来进行合并,然后再发送给namenode。
最常用的莫过于hive,将数据文件映射为数据表,可以将sql语句转换为map/reduce语句执行,其缺点是速度慢。
其次是hbase,一种基于列的分布式数据库。在需要快速查询的时候,一般我们会使用phoenix(封装了sql的hbase库),可以再结合图形界面squirrel。
impala,抛弃map-reduce架构,采用拉动式和内存式的方式进行数据查询。
Flume是一个日志收集系统,日志使用hdfs等存储,在离线分析场景下应用较多。Flume就如同一个大宗物件采购系统,从各个供应商处把形态各异的原材料存储到自己公司的多个仓库里面。Flume的架构包括agent、collector和storage,对应的分别是采购员(也包括司机)、原材料库保管员、仓库。此外,master相当于调度员(或者说原材料管理系统),client相当于供应商对接人,RPC协议相当于运输协议啦吗,里面指定运输地址、具体位置等。
Kafka是一个数据分发中间件,存储使用内存,一般用于低延时的在线分析场景。Kafka可以看做是一个消耗品的仓库管理系统,供应商不停的提供原材料,工厂不停的消耗原材料,其中涉及到库存管理和采购策略等可以配合其他中间件进行管理。Kafka的架构核心是broker,用topic来管理消息,负载均衡使用zookeeper来处理。kafka存储的分类区域名字叫topic,topic下每个分区是一系列文件夹,每个文件夹下又有一系列.log和.index文件。
我们现在有很多数据,都要进行一系列相同的计算工作,非常像是工厂里面有很多的原材料,需要进行一系列相同的生产组装工作。流计算和批计算的概念完全可以参照制造工厂的流水线和批量生产。
批计算中,任务在车间内处理完之后,不断堆积形成待运输在制品库存;等所有任务处理完之后,再移动到下一个车间。
流计算中,所有任务都在流水线上,仅有加工在制品,库存容量非常小,极端情况下甚至可以做到零库存(就像丰田倡导的那样)。
流计算并不等价于“实时”。就像流水线和批生产一样,只要批生产生产调度做的好,两者的生产周期时间完全可以相同。说到底,两者最大的差别还是“库存”,对应计算机的内存占用量。在批计算中,当生产任务非常大时(对应数据量非常大时),我们必须要人为的将原始的生产任务进行拆解(比如按照一定的数量分成一批一批的生产任务,每一批都有各自的生产批次),然后才能进行生产。
流计算可以看做是工厂生产中的流水线,这些中间件将原材料源源不断加工成想要的产品。spark2.3版本中引入了structured streaming代替了dsteam,既可以用mirco-batch模式,也可以用continuous mode的模式,功能已经非常完善了。可能是受到 Google Dataflow 的批流统一的思想的影响,Structured Streaming 将流式数据当成一个不断增长的 table,然后使用和批处理同一套 API,都是基于 DataSet/DataFrame 的。通过将流式数据理解成一张不断增长的表,从而就可以像操作批的静态数据一样来操作流数据了。下面是流计算中的一些重要概念:
窗口化:每个工位按照时间窗处理任务,形成“加工在制品”,称为窗口化。如果是设备每个一段时间启动一次处理所有产品,称为“处理时间窗口”;如果是每隔一段时间的产品累积完成之后启动设备开始处理,称为“发生时间窗口”。窗口化的本质是按照什么方式消费“加工在制品”的问题。
水位线:水位线可以理解为流水线工位之间的最大缓存量。如果某个工位出现了问题造成了在制品堆积,那么很快整个流水线就会卡住不动(上游堵塞,下游没有任务)。为了保持生产继续,一种解决方案就是把超过水位线的堆积在制品直接丢弃掉。
速度和一致性策略:对待生产线的波动的处理方式。比如某些任务在加工到一半的时候断电了,那么重启设备之后,任务需要重新开始加工,称为“至少一次”(at-least-once);如果断电后任务被丢弃,称为“最多一次”(at-most-once),可以参照银行扣款的场景,如果扣款环节因故中断,那么恢复连接后扣款任务要废弃,否则会发生重复扣款的风险;前者的一致性高,后者的速度快。
离线场景往往可以使用批计算的方式,这里仅介绍一下spark。spark从hdfs等地方获取到数据后,直接在内存(可以看做车间的线边仓)中进行数据处理,速度非常快。另外,spark的生态圈非常不错,机器学习、图形分析等库都很好用。
zookeeper是一个分布式应用程序协调服务,简单来说就是整个公司的综合统计,所有信息都在这里进行同步、更新和发布。
如同工厂调度人员、设备、仓储资源,以及原材料、在制品等资源,计算机也要调度cpu/内存/磁盘/数据等资源。与生产调度不一样的是,除了需求不确定外,生产周期时间也极具不确定性,很难用数学规划的方法去进行调度,只能用一些启发式的原则去进行控制。
YARN有几种管理方式(都算不上调度了):FIFO(先到先得所有资源)、capacity scheduler(有点像提前给每个工厂配好总资源,内部还是FIFO)、Fair Scheduler(不断平分资源)。
Mesos使用DRF,最大最小公平算法,可以对比为生产安排人与设备。有些需要的人多,有些需要的设备多,有些需要的库存空间多,以占用比例最大的作为产品的Dominant share(DS),循环分配资源给DS最小的产品,这样可以保证最小DS最大化~目前Mesos常常和Marathon配合,用于更高级别的集群管理。
这几个项目都是用于管理生产任务调度的,可以给每一个任务分配时间、资源,监控任务状态,观察进行中任务占用的资源等。
这里记录一下大数据实践过程中的关键点和踩过的坑。
首先你需要有几台服务器,将它们的name和ip都记录下来,然后将它们记录到每一台机器的/etc/hosts文件中,比如:
192.168.119.128 namenode
192.168.119.129 datanode1
192.168.119.130 datanode2
然后需要配置这几台机器之间的免密登录,这一步非常非常容易出错,一定要当心。首先先生成每台机器的密钥:
ssh-keygen -t rsa -P ‘’
然后将所有机器下/root/.ssh/id_rsa.pub的内容粘贴到authorized_keys文件,放在每台机器的/root/.ssh/目录下。
然后各个机器之间ssh来回登录一下,将首次免密登录需要输入的yes给搞定(不来回登录一下的话,之后hadoop安装可能会报错)。
安装hadoop时记住自己的用户名,不要随便用sudo!用sudo建立的目录是管理员权限,普通用户无法创建文件。
在每一台机器上创建hadoop的工作文件夹,比如:
mkdir /root/hadoop
mkdir /root/hadoop/tmp
mkdir /root/hadoop/var
mkdir /root/hadoop/dfs
mkdir /root/hadoop/dfs/name
mkdir /root/hadoop/dfs/data
然后下载一个hadoop放到namenode机器上然后解压缩,依次修改如下文件:
datanode1
datanode2
export JAVA_HOME=/usr/java/jdk1.8.0_66
hadoop.tmp.dir
/root/hadoop/tmp
fs.default.name
hdfs://namenode:9000
dfs.name.dir
/root/hadoop/dfs/name
dfs.data.dir
/root/hadoop/dfs/data
dfs.replication
2
dfs.permissions
false
mapred.job.tracker
hdfs://namenode:49001
mapred.local.dir
/root/hadoop/var
mapreduce.framework.name
yarn
yarn.resourcemanager.hostname
namenode
yarn.resourcemanager.address
${yarn.resourcemanager.hostname}:8032
yarn.resourcemanager.scheduler.address
${yarn.resourcemanager.hostname}:8030
yarn.resourcemanager.webapp.address
${yarn.resourcemanager.hostname}:8088
yarn.resourcemanager.webapp.https.address
${yarn.resourcemanager.hostname}:8090
yarn.resourcemanager.resource-tracker.address
${yarn.resourcemanager.hostname}:8031
yarn.resourcemanager.admin.address
${yarn.resourcemanager.hostname}:8033
yarn.nodemanager.aux-services
mapreduce_shuffle
yarn.scheduler.maximum-allocation-mb
8182
单个任务最大可申请内存,默认8182MB
yarn.nodemanager.vmem-pmem-ratio
2.1
yarn.nodemanager.resource.memory-mb
2048
该节点可使用内存
然后使用scp命令将hadoop文件夹复制到其他所有节点上。
执行初始化脚本:
hadoop-2.8.0/bin/hadoop namenode -format
启动hadoop:
hadoop-2.8.0/sbin/start-all.sh
可使用如下命令查看启动后的状态:
hadoop-2.8.0/bin/hadoop dfs admin -report查看hadoop状态
使用50060端口可以查看hadoop overview,使用8088端口可以查看hadoop集群情况。
下载spark on hadoop,解压缩到namenode上。将spark-2.1.1-bin-hadoop2.7/conf/spark-env.sh.template改为spark-env.sh,然后添加:
export JAVA_HOME =/usr/java/jdk1.8.0_66
export HADOOP_HOME =/root/hadoop-2.8.0
export HADOOP_CONF_DIR =$HADOOP_HOME/etc/hadoop
export SPARK_HOME = /root/spark-2.3.1-bin-hadoop2.7
export SPARK_MASTER_IP =namenode
export SPARK_EXECUTOR_MEMORY =4G
然后将spark拷贝到各个节点,真的是简单到不行。
在namenode的sbin目录下使用如下命令来启动python环境的spark,参数根据自己集群的情况进行修改。
pyspark --master yarn --deploy-mode client --num-executors 10 --driver-memory 8g --executor-memory 16g --executor-cores 4 --conf “spark.driver.host=namenode”
可以使用8080查看spark集群情况,用4040查看spark任务。
为了方便使用,可以修改/etc/profile:
export HADOOP_HOME=/root/hadoop-2.8.0
export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin
export SPARK_HOME=/root/spark-2.3.1-bin-hadoop2.7
export PATH=$SPARK_HOME/bin:$PATH
这里介绍一下hive安装的步骤,主要参考 https://blog.csdn.net/jssg_tzw/article/details/72354470
hive需要把元数据存储在数据库中,默认的derby不能多进程访问,因此这里使用mysql来存储。centos2.7 默认是没有mysql的,需要手动安装mysql。可以使用wget方式安装:
wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
rpm -ivh mysql-community-release-el7-5.noarch.rpm
yum -y install mysql mysql-server mysql-devel
启用服务并修改密码:
systemctl start mysqld.service
mysql -uroort
mysql>set password for root@localhost = password('123');
下载hive,上传到namenode服务器上,解压,同时创建一个/home/deploy/hive/tmp文件夹用于存放临时文件。在集群上建立如下文件夹:
hadoop fs -mkdir -p /user/hive/warehouse
hadoop fs -chmod 777 /user/hive/warehouse
hadoop fs -mkdir -p /tmp/hive/
hadoop fs -chmod 777 /tmp/hive/
修改/etc/profile,增加两行:
export HIVE_HOME=/home/deploy/apache-hive-2.1.1-bin
export HIVE_CONF_DIR=${HIVE_HOME}/conf
执行source /etc/profile使其生效。
进入conf文件夹,执行:
cp hive-default.xml.template hive-site.xml
将hive-site.xml中的${system:java.io.tmpdir}替换为hive的临时目录,将${system:user.name}都替换为root。
搜索javax.jdo.option.ConnectionURL,将该name对应的value修改为MySQL的地址,例如我修改后是:
javax.jdo.option.ConnectionURL
jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true
搜索javax.jdo.option.ConnectionDriverName,将该name对应的value修改为MySQL驱动类路径,例如我的修改后是:
javax.jdo.option.ConnectionDriverName
com.mysql.jdbc.Driver
搜索javax.jdo.option.ConnectionUserName,将对应的value修改为MySQL数据库登录名:
javax.jdo.option.ConnectionUserName
root
搜索javax.jdo.option.ConnectionPassword,将对应的value修改为MySQL数据库的登录密码:
javax.jdo.option.ConnectionPassword
123
搜索hive.metastore.schema.verification,将对应的value修改为false:
hive.metastore.schema.verification
false
下载mysql驱动 https://pan.baidu.com/s/1pLsA48F
上传到hive的lib文件夹下。
开启防火墙,添加3306端口:
systemctl start firewalld
firewall-cmd --permanent --add-port=3306/tcp
这样就能使用hive了。
如果要用spark连接hive,则将hive-site.xml放到spark的conf文件夹下,并添加
hive.metastore.uris
thrift://IP:9083
然后hive --service metastore&启用后台服务。
接着将mysql驱动放到spark的jars目录下,在pyspark中输入:
hive = SparkSession.builder.enableHiveSupport().getOrCreate()
即可在pyspark中使用hive。
官方地址下载kafka后,解压缩
tar -zxvf kafka_2.0.0-0.0.0.tar.gz
进入文件夹:
cd kafka_2.0.0-0.0.0
开启zookeeper和kafka
bin/zookeeper-server-start.sh config/zookeeper.properties >/dev/null 2>&1
bin/kafka-server-start.sh config/server.properties >/dev/null 2>&1 &
输入jps命令,可以看到Kafka和QuorumPeerMain两个进程,成功搞定!
创建一个test话题:
bin/kafka-create-topic.sh -zookeeper localhost:2181 -topic test
然后打开生产界面:
bin/kafka-console-producer.sh -broker-list localhost:9092 -topic test
在另一个窗口打开消费界面:
bin/kafka-console-consumer.sh -zookeeper localhost:2181 -topic test -from-beginning
在生产界面输入的所有文字,都会在消费界面出现,成功!
大数据常常涉及到多台机器集群的部署,为了方便统一管理,常常使用docker的方式。重要概念如下:
Docker:就是操作系统中的chroot。可以理解为你在写一篇论文的时候新建了一个文件夹,所有的东西都在这个文件夹里面。
Host:主机,运行容器的机器。比如我们自己的电脑。
Image:镜像,文件的层次结构,包含如何运行容器的元数据。可以比成一个论文模板。
Container:容器,从镜像启动,包含正在运行的程序的进程。可以比成我们电脑里打开的论文。run相当于打开论文模板,修改后commit相当于保存论文。start,stop就相当于打开论文、关闭论文。一个container等于一个image+运行指令等参数
Registry:镜像仓库。可以比成论文模板库。pull就相当于从论文库下载模板到自己的电脑上。
Volume:容器外的存储。可以比成论文里面链接的文件夹。
Dockerfile:用于创建镜像的脚本。可以比成普通的word程序。
运行docker Linux内核版本需要在3.8以上,内核为2.6的系统需要先升级内核,不然会特别卡。常用命令如下:
yum -y install docker-io:安装docker
service docker start:启动docker
docker version:查看版本
cat /var/log/docker:查看日志
搜索查看类命令:
docker info:查看docker相关信息。image和container都有id和name:tag两种方式。不加tag的话默认是latest。
docker search [IMAGE]:查找镜像库
docker pull [IMAGE] 拉取镜像
docker images/docker image ls:查看本地镜像
docker ps :查看容器状态;-a,所有;-l,最近。
docker logs [CONTAINER]:查看容器标准输出
docker port [CONTAINER]:查看网络端口映射情况
启动关闭类命令:
docker run -it [IMAGE] [COMMAND]:启动交互界面,运行镜像的命令;使用exit退出
docker run -d [IMAGE] [COMMAND]:启动后台模式;-P:将容器内部使用的网络端口映射到我们使用的主机上。-name:给容器命名
docker build [IMAGE]:通过Dockerfile创建镜像
docker start/stop/restart/attach [CONTAINER/ID]:操作容器,其中attach是切换到相应容器
docker commit -m -a [CONTAINER] [NEW IMAGE]:容器保存为镜像
docker rmi [IMAGE] :删除镜像
docker rm [CONTAINER] :删除容器
docker ps -a -q/docker container ls -a:查看所有容器ID
docker rm $(docker ps -a -q):删除所有的容器
docker inspect [CONTAINER|IMAG]:查看容器或镜像的详细信息
仓库搭建:
https://blog.csdn.net/u010397369/article/details/42422243
https://blog.csdn.net/boling_cavalry/article/details/78818462
仓库使用:
docker push username/repository:tag
docker run username/repository:tag