备份
mysqldump -u 用户名 -p 数据库名 > 磁盘SQL文件路径
dos窗口使用
恢复
mysql -u 用户名 -p 导入库名 < sql文件路径
笛卡尔积
select * from a,b;
即做笛卡尔积返回
还需要加入过滤条件
内连接
select * from A inner join B on A.A_ID=B.B_ID
左外连接
select * from A left outer join B on A.A_ID=B.B_ID
区别:左外连接如果没有关联上左表也会显示,以左为主
全外连接
select * from A full outer join B on
左外与右外结果合并,去除重复记录
exist–有结果返回则为true,则显示主查询结果
union和union all
select *,
case
when salary <5000 then ""
when salary >=5000 then ""
end as level,
case sex
when "famale" then 1
when "male" then 0
end as flag
from employee;
select VERSION() //服务器版本
show state //服务器状态
show variables //服务器配置变量
常见函数
char_length(s) //字段长度
concat("","",...) //拼接字段 concat_WS()加个分隔符
format(,) //格式化数字,后面数为保留几位
LCASE(s) //转小写
TRIM(s) //去掉字符串开始结尾的空格
ABS(s) //绝对值
CEIL(x) //向上取整
RAND() //01随机数
日期函数
adddate(d,n) //计算真实日期D加上N天的日期
curdate() //当前日期
current_timestamp //返回当前日期和时间 --now()
datediff(d,f) //两个日期差多少天
date_add("yyyy-mm-dd hh:mm:ss",interval 1 day) //加上一天
date_format(d,f) //按f格式显示日期d
高级函数
cast("2022-01-09" as DATE) //转换数据格式
coalesce(...) //返回第一个非空数据
create index index_name on mytable(username(length));
//对某字段一段长度
create index id on (B_id);
//普通索引
//改表结构添加索引
alter table tablename add indexname(columnName)
//建表直接指定
create table mytable(
id int not null,
username varchar(16) not null,
index [indexName](username(length))
);
//删除索引
drop index [indexname] on mytable;
唯一索引
索引列的值必须唯一,但允许控制
alter table tablename add primary key (column_list);
索引值必须唯一
alter table tableName add unique index_name (column_list);
创建索引的值必须是唯一的(除了null)
alter table tableName add index index_name(column_list);
普通索引,索引值可出现多次
alter table tableName add fulltext index_name(dolumn_list);
用于全文索引
show index from table_name;
MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。
https://www.cnblogs.com/pebblecome/p/14815340.html
目前mysql只有Innodb数据库引擎支持事务
ACID
原子性–
一致性–事务必须保持系统的一致性状态,不论并发。
隔离性–允许并发事务,防止多个事务执行交叉执行导致数据不一致
持久性–事务结束对数据的修改就是永久的
innodb/Myisam比较多
相当于事务型和分析型差别
可分别用来实现读写分离
ls/ll
ls -l 和ll一样
当前目录
pwd
ctrl C和ctrl Z
前者取消后者结束
mkdir dir1[dir2 dir3 dir4]
删除
rm -rf dir
递归创建
mkdir -p dir1/dir2/dir3 scp -r分发
yum 安装
install -y telnet
自动补全
tab
查看进程
ps -ef | grep impala
查看文件
cat /more /tail -f 大文件不用cat
分发
scp -r /export/servers/hadoop hadoop02:/export/servers
scp -r /export/servers/hadoop hadoop02:$PWD(发到同级目录)
date 日期 可以+“%Y-%m-%d %H-%M-%S”
添加用户
useradd username
更改密码
password username
删除用户
userdel username(不删除用户数据)
userdel -r username
磁盘大小
df -h
内存大小
free -h
文件大小
du -h
任务管理器
top
清理内存
echo 1 > /proc/sys/vm/drop_caches
尝试
hadoop1.0和2.0差别
hadoop块大小为什么是128m?
在物理是分块存储(block)
Hadoop2.x以上都是128m,在集群运行的是128m,在本地运行的时候是64m
文件的寻址时间为传输时间的1%的时候,为最佳状态,寻址时间一般为10ms,
所以最佳的传输时间为10ms/1%为1000ms,也就是1s
目前的硬盘传输速率是100m/s,所以文件的大小在100m左右的时候,传输速率较高。
为什么不能随机写?
hdfs 是块存储,也就是每次读取一个块,存储也是一样的,所以你可以理解为可以随机读写文件块,但是对文件不支持随机读写,因为一个文件块中可能有很多文件。
启动hadoop
查看hadoop启动进程
查看50070、8088等端口
记忆==
namenode:HDFS主节点,存储元数据
datanode:工作节点,存储数据,读写数据
secondarynamenode:守护进程,备份NN元数据
resourceManager:yarn主节点,资源调度分配,监控NM
nodeManager:资源管理,听RM的
DFZKFC:高可用监控NN状态,写入ZK
JournalNode:高可用存NN的editlog
hadoop-env.sh-------配置环境变量
core-site.xml----------设置hadoop文件系统地址(fs.defaultFS->dfs://hadoop01:9000)
hdfs-site.xml---------副本数量,secondaryNN Ip和端口
mapred-site.xml-----MR运行时框架,默认local,可yarn
yarn-site.xml---------yarn主节点地址
初始化
hadoop namenode -format
启动dfs
start-dfs.sh
启动历史服务器
mr -jobhistory-daemon.sh start historyserver
一键启动
start-all.sh
NameNode 50070
ResourceManager 8080
hdfs -put
修改core-site.xml
添加fs.trash.interval 1440 1440=24h=1day
SNN不是NN的热备份,职责为合并edits log文件并分担NN的压力,必要时协助恢复NN
NameNode HA
共享存储QJM 保存editlog不保存fsimage
当前active NN 的ZKfailoverController进程发生假死,ZK会认为当前active NN挂掉,NN2会替代进入active状态,此时有两个active NN运行
fencing隔离,把旧的active NN隔离
此状态下,文件系统只接受读数据请求,不接受删除,修改等请求。
NN启动时,HDFS进入安全模式,集群检查数据块完整性。DN启动会向NN汇报可用block信息,整个系统达到安全标准时,HDFS自动离开安全模式。
手动进入安全模式
hdfs dfsadmin -safemode enter
手动离开
hdfs dfsadmin -safemode leave
hadoop本身没有此能力,需要配置一个脚本进行映射,或者通过实现DNSToSwitchMapping接口的resolve()方法来完成网络位置映射。
map类
public class wordCountMapper extends Mapper<LongWritable,Text,Text,IntWritable>{
//map生命周期:框架每传一行数据就被调用一次
//key:这一行的起始点在文件中的偏移量
//value:这一行的内容
@override
rotected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException{
String line = value.toString();
String[] words = line.split(",");
for(String word:words){
context.write(new Text(word),new IntWritable(1));
}
}
}
reduce类
public class WordCountReducer extends Reducer<Text,IntWritable,Text,IntWritable>{
//map到reduce之间有一个shuffle过程,将map输出数据打乱
//来一组执行一次
@override
protected void reduce(Text key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException{
int count=0;
for(IntWritable value:values){
count+=value.get();
}
context.write(key,new Intwritable(count));
}
}
需要注意问题:文件很小先进行小文件合并,自定义分区需要设置reduce个数,如果输出路径已经存在会报错,打包放到linux运行没有设置jar的话会报错.setJar .setJarByClass
scala实现
array.flatMap(x=>x.split(",")).groupBy(_._1).map(x._1,x._2.length)
spark离线实现
val sparkconf=new sparkConf().setAppName("wordCount").setMaster(args(0))
val SC = new sparkContext(sparkconf)
val lines = ssc.socketTextStream("localhost",9999)
每一个map都可能产生大量本地输出,Conbiner是对map端的输出先做一次合并,减少map和reduce节点间的数据传输量,提高网络io性能
执行MR计算时,有时需要对最终输出分到不同文件中,就需要partitioner
map的shuffle阶段做分区
实现
@override
public int getPartition(IntWritable key,IntWritable value,int numPartitions){
int intValue = key.get();
if(intValue % 5==0){
return 0;
}else{
return 1;
}
}
主类函数加
job.setPartitionerClass(classname.class);
job.setNumReduceTasks(2);设置为2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wYngImRq-1664110283006)(C:\Users\宋大帅\AppData\Roaming\Typora\typora-user-images\image-20220223123455697.png)]
inputformat数据读取
Split将获取数据逻辑切分
获得数据对数据逻辑切分,切分128M,和HDFS存储数据块128M没关系,一个是存储层面一个是计算层面,一个集成程序正好一个数据块。
recordReader 以行切分,输出
Map 接受KV根据重写的map函数输出KV的list
shuffle=>
reduce按照重写reduce方法做汇总计算
outputformat写入HDFS
采用CombineFileInputFormat来作为输入,解决输入端大量小文件场景
合理设置Map和Reduce数:两个都不能设置太少,也不能设置太多。太少,会导致Task等待,延长处理时间;太多,会导致 Map、Reduce任务间竞争资源,造成处理超时等错误。
采用数据压缩的方式,减少网络IO的的时间
Map和reduce task的可用内存扩大(条件允许的话)以及每个task的cpu核加
压缩,可以参考这张图
:如果面试过程问起,我们一般回答压缩方式为Snappy,特点速度快,缺点无法切分(可以回答在链式MR中,Reduce端输出使用bzip2压缩,以便后续的map任务对数据进行split)
https://blog.csdn.net/a934079371/article/details/109233998
client提交一个任务到RM
RM到NodeManager申请一个容器container,然后启动一个appMaster
ApplicationMaster陆续为app包含的每个task向ResourceManager申请一份container
得到container后要求该container所属的NM启动container,执行相应的task
执行完task后此container会被NodeManager回收
client=>RM=>(container)appMaster=>ResourceManager=>container(task)=>回收
client对集群HDFS没权限
通用资源管理系统和调度平台,为上层应用提供统一的资源管理和调度。有点像一个分布式的操作系统平台,mapreduce等运算程序相当于运行于操作系统的应用程序,yarn为它们提供运算所需资源。
ResourceManager 负责资源监控、分配和管理
NodeManager 负责每个节点的维护
ApplicationMaster 负责每个具体应用的调度和协调
RM只监控AM,在AM失败启动它,不负责AM容错,AM自己完成
sqoop时apache旗下hadoop和关系型数据库服务器之间传输数据的工具
导入数据:MYSQL,Oracle导入数据到Hadoop的HDFS、Hive、Hbase等数据存储系统
导出数据:从hadoop的文件系统中导出数据到关系型数据库mysql等
将导入导出命令翻译成mapreduce程序来实现
mysql到hdfs
bin/sqoop import \
--connect jdbc:mysql://hadoop01:3306/A \
--username root \
--password 123456 \
--target-dir /A2 \
--table B --m 1
mysql导入hive(可能乱码)
bin/sqoop import \
--connect "jdbc:mysql://hadoop01:3306/A?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table B \
--hive-import \
--m 1 \
--hive-database default;
hdfs导入mysql
bin/sqoop export \
--connect "jdbc:mysql://hadoop01:3306/A?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table B \
--export-dir /user/hive/warehouse/b
解决:加characterEncoding=utf-8
hive注释会乱码
https://www.cnblogs.com/qingyunzong/p/8724155.html
是因为mysql中元数据乱码
配置文件把相应注释的地方的字符集由 latin1 改成 utf-8
目标数据过大,调大datax的jvm参数防止oom
python datax.py --jvm="-Xms5G -Xmx5G"
字段长度过长
数据源column字段长度超过100000字符
"csvReaderConfig":{
"safetySwitch":false,
}
bigtable的开源java版本,是建立在hdfs之上,提供高可靠性、高性能、列存储、可伸缩、实时读写nosql的数据库系统
主要应用:海量数据的并发读写,分析需求较小。原生不支持二级索引和sql,需在其上架构Phoenix、spark等。
mapreduce操作hbase,多少个region就有几个map
Redis
分布式缓存,基于内存,强调缓存,支持数据持久化,支持事务,nosql类型的key/value数据库,同时支持List,set等类型
Hbase
hbase是建立在hdfs上的,提供高可靠性的列存储。介于Nosql和关系型数据库之间,仅通过主键和主键的range来检索数据,仅支持单行事务。主要用来存储结构化和半结构化数据。
关系型数据库
mysql、oracle等,支持事务型,属于写模式,即写入数据时进行检查。针对具体业务在数据库练级的日常操作,通常对少数记录进行查询、修改。支持完善的sql功能,可对少量数据进行统计分析。
hive
基于hadoop的数据仓库工具,可以将结构化数据文件映射为数据库表,可以将sql转化为mr任务执行。因为sql比mr学习成本低,适合数据仓库的统计分析。
区别
关系型数据库和HIve都支持sql引擎。redis和hbase都是nosql类型key value数据库,支持简单的行列操作,不支持sql引擎。
redis因为存储在内存数据量较小,hbase适合大数据的持久储存,redis适合做缓存。EDMBMS一般用来做支撑业务系统。hive时面向分析的分析型工具,作为海量数据的分析工具。
hive和hbase是基于hadoop的两种不同技术。hive是一种类sql引擎,且运行MR任务,Hbase是一种在hadoop之上的nosql的k、v数据库。两者可以搭配使用,hive用来做统计查询,hbase用来做快速实时查询。可将hive映射到hbase,做对外的访问接口。
启动
先启动hdfs和zk
start -hbase.sh
hd50070 yarn8088 hbase16010
进入HBase客户端命令操作界面
bin/hbase shell
查看表
list
创建user表(包含info、data两个列族)
create 'user','info','data'
create 'user',{NAME=>'info',VERSIONS=>'3'},{NAME=>'data'}
添加数据
user表插入一行信息,rowkey为0001,列族info添加name列标示符,值为zhangsan
put 'user','rk0001','info:name','zhangsan'
put 'user','rk0001','info:gender','female'
查询操作
通过rowkey
get 'user','rk0001'
某个列族信息
get 'user','rk0001','info'
指定列族指定字段
get 'user','rk0001','info:name','info:age'
所有数据
scan 'user'
列族查询
scan 'user',{COLUMNS=>'info'}
统计
count 'user'
显示所有表
list
row key是用来检索记录的主键,访问行:
列族
列族是表的schema的一部分而列不是
列名都以列族做前缀如Family1:name
列族越多,取一行数据要参与的io就越多,非必要不设太多列族
cell
通过row和columns确定的一格为cell ,每个cell保存一份数据的多个版本,通过时间戳区分
写
读
不做的话全部默认在一个region,太大,读写很慢
根据rowkey划分
作用
手动设定预分区
create 'staff','info','partition1',Split=>['1000','2000','3000','4000']
16进制算法生成预分区
create 'staff2','info','partition2',{NUMREGION=>15,SPLITALGO=>'HexStringSplit'}
三原则
长度原则
每个cell单元格都会保存rowkey,尽量不超过16字节,太长资源浪费
散列原则
如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位字节采用散列字段处理,由程序随即生成。低位放时间字段,这样将提高数据均衡分布,各个regionServer负载均衡的几率
rowkey是按字典序存储,将经常一起读的数据存储到一块,将最近可能被访问的数据放到一块。
例:如果最近写入的最可能被访问,因为是字典序排序可以使用Long.MAX_VALUE-timestamp作为rowkey
唯一原则
保证唯一性
rowkey是按字典序存储,将经常一起读的数据存储到一块,将最近可能被访问的数据放到一块。
热点问题
大量的client直接访问集群的一个或极少数节点,使热点region所在的节点超出承受能力,性能下降或不可用,同一region Server的其它region也被影响。
解决方案
加盐
在rowkey前加随机数,使其和之前rowkey开头不同。之后rowkey根据前缀不同分散到各个region避免热点
哈希
哈希使同一行一直用一个前缀加盐。也可以使负载分散到整个集群,但是读是可预测的。可用get准确获取某一行数据
反转
如手机号,反转一下,避免因为前几位太相同而都分到一个region。
时间戳反转
常见情景是快速获取最近版本数据,反转时间戳作为rowkey一部分非常有用,可Long.MAX_VALUE-timestamp追加到key末尾
由c编写的nosql类型的开源key-value存储系统。redis数据都缓存在系统内存中,可周期性把更新数据写入磁盘或把修改操作写入追加的记录文件,实现数据持久化。
string
赋值 set key value
取值 get key/getset key value
数据自增和自减 incr key/decr key
拼凑 append key value
hash
适合存储对象
赋值hset key field value(hset student name sp)
取值 hget key field
取值 hgetall key
删除 hdel key field[field..]
删除 del key
判断是否存在 hexist key field
获取所有key hkeys key
获取所有value hvals key
list
list基本使用
redis会定期保存数据快照至一个rdb文件中,并启动时自动加载rdb文件恢复数据。快照保存时机可配置。
redis把每个写请求记录在日志文件里,redis重启会把日志的写操作全做一遍。AOF默认关闭的
开启
appendonly yes
三种sync配置,always/everysec/no,通过配置项appendfsync指定
优点
缺点
一定不存在数据,每次都不会命中要去数据库查。黑客通过这点不停请求数据库,失去了缓存意义。数据库炸。
**解决**
1.布隆过滤器(比如是id就先把所有id写进布隆过滤器,有的话才查)或压缩过滤提前拦截
2.数据库找不到的时候也把空对象设置到redis中。
解决:
访客管理项目中
flink实践
在过期时间上再加了个10秒随机时间假设了缓存雪崩场景。
注意版本问题,尤其和spark的
scala编写的一个高吞吐的分布式发布订阅系统
项目里的使用
常见消息队列
RabbitMQ、Redis、zeroMQ、ActiveMQ(吞吐量小,容易阻塞)
kafka的优势
zookeeper集群:保存了生产者、broker、消费者元数据
如消费者的偏移量(高级保存到zk、低级的在kafka)、分区的主分区等
消费者和生产者能操作的最小单元是分区,也就是不可能只消费一条数据
所以分区内有序但整体不一定有序
★同一个消费者组里面不能是同时消费者消费消息,只能有一个消费者去消费
没有指定分区号、没指定key根据轮询的方式发送到不同分区
没有指定分区号,指定了key,根据key.hashcode%numPartition
可以给key加个随机值避免数据倾斜
指定了分区号、指定了key,数据写到指定分区
自定义分区策略
生产者方面
同步模式:配置=1(只有leader收到,-1所以副本成功,0不等待)leader挂了数据丢失
解决:设置-1,写入所以副本才算成功
异步模式:当缓冲区满,如果配置为0(没有收到确认,一满就会丢弃),数据立刻丢弃
解决:不限制阻塞超时时间。一满生产者就阻塞
broker方面
consumer方面
消费数据到hbase或者mysql中,如果hbase在这个时候连接不上(网络抖动),会抛出异常,如果在处理数据的时候已经进行了提交,那么kafka上的offset已经进行了修改,但是hbase没有数据,造成数据丢失。主要因为offset使用了异步提交
解决:
落表(主键或唯一索引的方式,避免重复数据)
业务逻辑处理(选择唯一主键存储到redis或mongodb,查询是否存在,不存在则先插入在进行业务逻辑处理)
数据过大也可考虑布隆过滤器
分区中以segment段划分,达到一个g划分一个segment
通过offset确定数据在哪一个segment
查找对应的segment里面的index文件,index文件哦都是key/value对的。key为log中对应的顺序,value记录了这条数据在全局的标号。如果能直接找到对应的offset直接去获取对应数据
如果index文件里没有存储offset,就会找最近的一个offset,例如找不到7就去6,再取下一条数据
earliest
分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时从头开始消费
latest
当分区下有已提交offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
none
topic各分区都存在已提交offset时,从offset后开始消费;只要有一个分区不存在已提交offset则报错
latest情况(默认)
先发送了几条消息 1 2 3——————》topic order
此时启动消费者1,所有分区都没有offset,不消费
又发送了几条消息 4 5 6 -------》topic order
此时消费者可消费到4 5 6,但 1 2 3 消费不到
earliest
先发送了几条消息 1 2 3——————》topic order
此时启动消费者1,此时无offset,从头消费 1 2 3
又发送了几条消息 4 5 6 -------》topic order
消费者正常消费
latest容易丢失消息,如果kafka突然出错,依然在往topic写入,此时重启kafka会按最新offset开始消费,前面的就丢失了
https://www.cnblogs.com/gxgd/p/8671271.html
简而言之
开源分布式全文检索引擎,近乎实时存储检索数据。扩展性良好。
信息检索相关企业可用,法律类、车管类、金融类
Relational DB-> Database ->Tables ->Rows ->Columns
Hbase -> nameSpace->ns:Table ->rowkey ->列族下一个个列
ElasticSearch ->Index -> Types -> Documents->Fields
类型在7.x版本以后消失
1.创建索引
curl -XPUT http://node01:9200/blog01/?pretty
2.插入文档
curl -XPUT http://hadoop01:9200/blog01/article/1?pretty -d '{"id":"1","title":"what is lecene"}'
3.查询文档
curl -XGET http://hadoop01:9200/blog01/article/1?pretty
4.更新文档
curl -XPUT http://hadoop01:9200/blog01/article/1?pretty -d '{"id":"1","title":"what is elasticsearch"}'
5.搜索文档
curl -XGET "http://hadoop01:9200/blog01/article/_search?q=title:elasticsearch"
6.删除文档
curl -XDELETE "http://hadoop01:9200/blog01/article/1?pretty"
7.删除索引
curl -XDELETE http://hadoop01:9200/blog01?pretty
返回值说明
apache spark是用于大规模数据处理的统一的分析计算引擎
基于内存计算,提高实时性,同时保证了高容错和高可伸缩性。
spark比较吃内存,不能像hadoop部署在廉价机器上
从项目介绍自己的使用
spark相比hadoop有较大优势,但并不完全替代hadoop,spark主要用于替代hadoop中的mapreduce计算模型,存储依然可使用hdfs,但是中间结果放内存中,调度可用spark内置的也可用成熟的yarn调度。
个人使用时是部署的with hadoopXX版本,借助yarn实现资源调度管理,借助hdfs分布式存储
spark对硬件要求比hadoop要高,对内存和cpu有一定要求
快
与hadoop的mapreduce相比,spark基于内存的运算要快100倍以上,基于硬盘的运算也要快10倍以上,spark实现了高效的DAG执行引擎,可通过基于内存来高效处理数据流
易用
spark支持多种语言,以及很多高级算法,且支持交互式的scala和python的shell。
通用
提高了统一的解决方案,批处理、交互式查询(sparksql)、实时流处理(streaming)、机器学习(MLlib)和图计算(GraphX)。减少开发和维护的成本
兼容性
方便和其它开源产品融合,可使用yarn和mesos作为资源管理和调度器,可处理hadoop支持的数据。方便搭建了hadoop集群的不需要做数据迁移即可使用spark的计算处理。同时standalone也可以不依赖第三方。
local本地模式
本地开发使用,idea线程模拟
standalone
开发测试用,master/slave模式
Stand alone-HA
使用zk搭建高可用
on yarn集群
由yarn负责资源管理,spark负责任务调度和计算。
计算资源按需伸缩,集群利用率高,共享底层存储。
FIFO(大小任务在一个队列容易阻塞)
Fair:公平调度
Capacity(容量):默认的,多一个队列,大任务和小任务
on mesos
运行在mesos资源管理框架,国内用的少
on cloud
如AWS和EC2,
提交任务和交互式测试,入门学习使用
spark-shell --master local[N\*]
spark-shell --master spark://hadoop01:7077,hadoop02:7077
##集群上
提交到standalone
/export/servers/spark/bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master saprk://hadoop01:7077 \
--executor-memory 1g \
--total-executor-cores 2 \
/export/servers/spark/examples/jars/spark-examples_2.11-2.2.0.jar \
10
提交到standalone-HA
/export/ servers/spark/bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop01:7077,hadoop01:7077 \ #轮询
--executor-memory 1g\
--total-executor-cores 2 \
/export/servers/spark/examples/jars/spark-examples_2.11-2.2.0.jar \
10#并行度
提交到yarn集群(cluster) 生产中大多为cluster部署模式
/export/servers/spark/bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
--driver memory 1g \ #收集最终结果时,广播变量时
--executor-memory 1g \
--executor-cores 2 \
--queue default \
/export/servers/spark/examples/jars/spark-examples_2.11-2.2.0.jar \
10
#Driver是在nodemanager节点上的
提交到yarn(client) 学习测试时使用
driver在客户端上
客户端影响很大,客户端终止了任务就终止了
/export/servers/spark/bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode client \
--driver memory 1g \ #收集最终结果时,广播变量时
--executor-memory 1g \
--executor-cores 2 \
--queue default \
/export/servers/spark/examples/jars/spark-examples_2.11-2.2.0.jar \
10
集群下需修改参数
1.setMaster需去掉,提交时指定
2.路径需修改(定为个参数)
弹性分布式数据集
不可变,可分区,元素可并行计算的集合。
5.数据本地性
读取文件(sc.textFile)(wholeTextFile:文件夹下大量小文件KV)
通过已有rdd转换
读取scala集合创建(sc.parallelize)
map和mapPartitions
前者处理一个个元素,后者为处理一个个分区内的数据集合(迭代器)
reduceByKey和groupByKey
reduceByKey性能更高,会在map端进行一次聚合,后者没有,则造成更多的磁盘文件读写,以及网络传输损耗更多
join
宽窄依赖
reparttion和coalesce
collect
数组形式返回数据集到driver
conutByKey
可检查数据倾斜,查看key分布情况
foreach和foreachPartition
例如在连数据库时,数据量大的话不能foreach对每一个元素,
更加可靠的数据持久化,放到HDFS上,比内存和磁盘都安全。实现了rdd的高容错和高可靠。
sc.setcheckpointDir( "hdfs://hadoop01:8020/ckpdir")
//设置检查点目录,会立即在HDFS上创建一个空目录
val rdd1 = sc.textFile("hdfs://node01:8020/wordcount/input/words.txt").flatMap(_ .split(" ")).map(( ,1)).reduceByKey(_+_)
rdd1.checkpoint //对rdd1进行检查点保存
rdd1.collect //Action操作才会真正执行checkpoint
//后续如果要使用到rdd1可以从checkpoint中读取
位置
persist和cache只能保存在本地
checkpoint可用保存数据到HDFS这类可靠的存储上
生命周期
cache和persist的RDD会在程序结束后被清除或手动调用unpersist方法
checkpoint的RDD在程序结束依然存在,不会被删除
依赖关系
persist和cache不会丢掉RDD间的依赖关系,因为这种缓存不可靠,如果出现问题需要回溯依赖关系重新计算
checkpoint会斩断依赖链,因为checkpoint会把结果保存在HDFS这类存储中,更加安全可靠,一般不需要回溯依赖链
shuffle影响性能,窄依赖能并行计算(shuffle产生磁盘io、网络io、产生排序)
窄依赖
宽依赖
特殊
join可以是宽依赖也可以是窄依赖
如果在join之前做groupbyKey就不会发生shuffle了
数据转换执行的过程,有方向无闭环(RDD执行流程)
原始的RDD通过一系列转换操作形成了DAG有向无环图,任务执行时可以按照DAG描述,执行真正的计算。
一个Spark应用中可以有一到多个DAG,取决于触发了多少次action。一个DAG代表一个Job**
每个DAG划分为stage,stage可以并行计算。
为什么要划分stage?
一个复杂逻辑如果有shuffle,意味着前面阶段产生结果才能执行下一阶段。按宽窄依赖进行划分,在同一个stage可以并行执行平行的分区。
如何划分stage和task?
spark根据shuffle使用回溯算法对DAG进行stage划分,从后往前,遇到宽依赖就断开,遇到窄依赖就把当前RDD加入到当前stage。
每个 stage 里面 task 的数目由该 stage 最后一个 RDD 中的 partition 个数决定。
DF前身为SchemaRDD,1.3之后不再继承自RDD。
是一种以RDD为基础的分布式数据集,类似数据库二维表,带有schema元信息。
1.6添加的新接口
与RDD相比保存了更多描述信息,类似二维表。
与DF相比,保存了类型信息,强类型的,有编译时的类型检查。
2.0后两者统一,DF表示为DS[Row]
DF=RDD-泛型+schema+SQL+优化
DF=DS[Row]
DS=DF+泛型
DS=RDD+Schema+SQL+优化
创建DF
由一个RDD,绑定样例类person,然后.toDF
注册表 .createOrReplaceTempView(“table_name”)
然后进行sql操作
也可以直接读文件为DF,但是没有完整schema信息
或者读parque文件或者json,方便。
指定列名转换DF
//指定类型
val rowRDD = linesRDD.map(line=>{line(0).toInt,line(1),line(2).toInt})
val personDF = rowRDD.toDF("id","name","age")
sparkStreaming基于spark core之上的实时计算框架。高吞吐和高容错。
Dstream本质上就是一系列时间上连续的RDD
package cn.itcast.streaming
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext}
object WordCount3 {
def main(args: Array[String]): Unit = {
//1.创建StreamingContext
//spark.master should be set as local[n], n > 1
val conf = new SparkConf().setAppName("wc").setMaster("local[*]")
val sc = new SparkContext(conf)
sc.setLogLevel("WARN")
val ssc = new StreamingContext(sc,Seconds(5))//5表示5秒中对数据进行切分形成一个RDD
//2.监听Socket接收数据
//ReceiverInputDStream就是接收到的所有的数据组成的RDD,封装成了DStream,接下来对DStream进行操作就是对RDD进行操作
val dataDStream: ReceiverInputDStream[String] = ssc.socketTextStream("node01",9999)
//3.操作数据
val wordDStream: DStream[String] = dataDStream.flatMap(_.split(" "))
val wordAndOneDStream: DStream[(String, Int)] = wordDStream.map((_,1))
//4.使用窗口函数进行WordCount计数
//reduceFunc: (V, V) => V,集合函数
//windowDuration: Duration,窗口长度/宽度
//slideDuration: Duration,窗口滑动间隔
//注意:windowDuration和slideDuration必须是batchDuration的倍数
//windowDuration=slideDuration:数据不会丢失也不会重复计算==开发中会使用
//windowDuration>slideDuration:数据会重复计算==开发中会使用
//windowDuration
//下面的代码表示:
//windowDuration=10
//slideDuration=5
//那么执行结果就是每隔5s计算最近10s的数据
//比如开发中让你统计最近1小时的数据,每隔1分钟计算一次,那么参数该如何设置?
//windowDuration=Minutes(60)
//slideDuration=Minutes(1)
val wordAndCount: DStream[(String, Int)] = wordAndOneDStream.reduceByKeyAndWindow((a:Int,b:Int)=>a+b,Seconds(10),Seconds(5))
wordAndCount.print()
ssc.start()//开启
ssc.awaitTermination()//等待优雅停止
}
}
package cn.itcast.streaming
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext}
object WordCount2 {
def main(args: Array[String]): Unit = {
//1.创建StreamingContext
//spark.master should be set as local[n], n > 1
val conf = new SparkConf().setAppName("wc").setMaster("local[*]")
val sc = new SparkContext(conf)
sc.setLogLevel("WARN")
val ssc = new StreamingContext(sc,Seconds(5))//5表示5秒中对数据进行切分形成一个RDD
//requirement failed: ....Please set it by StreamingContext.checkpoint().
//注意:我们在下面使用到了updateStateByKey对当前数据和历史数据进行累加
//那么历史数据存在哪?我们需要给他设置一个checkpoint目录
ssc.checkpoint("./wc")//开发中HDFS
//2.监听Socket接收数据
//ReceiverInputDStream就是接收到的所有的数据组成的RDD,封装成了DStream,接下来对DStream进行操作就是对RDD进行操作
val dataDStream: ReceiverInputDStream[String] = ssc.socketTextStream("node01",9999)
//3.操作数据
val wordDStream: DStream[String] = dataDStream.flatMap(_.split(" "))
val wordAndOneDStream: DStream[(String, Int)] = wordDStream.map((_,1))
//val wordAndCount: DStream[(String, Int)] = wordAndOneDStream.reduceByKey(_+_)
//====================使用updateStateByKey对当前数据和历史数据进行累加====================
val wordAndCount: DStream[(String, Int)] =wordAndOneDStream.updateStateByKey(updateFunc)
wordAndCount.print()
ssc.start()//开启
ssc.awaitTermination()//等待优雅停止
}
//currentValues:当前批次的value值,如:1,1,1 (以测试数据中的hadoop为例)
//historyValue:之前累计的历史值,第一次没有值是0,第二次是3
//目标是把当前数据+历史数据返回作为新的结果(下次的历史数据)
def updateFunc(currentValues:Seq[Int], historyValue:Option[Int] ):Option[Int] ={
val result: Int = currentValues.sum + historyValue.getOrElse(0)
Some(result)
}
}
package cn.itcast.streaming
import kafka.serializer.StringDecoder
import org.apache.spark.streaming.dstream.{DStream, InputDStream}
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext}
object SparkKafka2 {
def main(args: Array[String]): Unit = {
//1.创建StreamingContext
val config: SparkConf =
new SparkConf().setAppName("SparkStream").setMaster("local[*]")
val sc = new SparkContext(config)
sc.setLogLevel("WARN")
val ssc = new StreamingContext(sc,Seconds(5))
ssc.checkpoint("./kafka")
//==============================================
//2.准备配置参数
val kafkaParams = Map("metadata.broker.list" -> "node01:9092,node02:9092,node03:9092", "group.id" -> "spark")
val topics = Set("spark_kafka")
val allDStream: InputDStream[(String, String)] = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParams, topics)
//3.获取topic的数据
val data: DStream[String] = allDStream.map(_._2)
//==============================================
//WordCount
val words: DStream[String] = data.flatMap(_.split(" "))
val wordAndOne: DStream[(String, Int)] = words.map((_, 1))
val result: DStream[(String, Int)] = wordAndOne.reduceByKey(_ + _)
result.print()
ssc.start()
ssc.awaitTermination()
}
}
1.2之前都是hash based shuffle
1.2之后是sort based shuffle
未优化前有大量中间小文件
优化后合并了中间小文件
map任务按分区id和key对记录进行排序,然后放入内存缓存,全部结果写入一个数据文件,同时生成一个索引文件。类似mapreduce的shuffle
tungsten 优化
使用堆外内存和新的内存管理模型。节省了内存空间和大量gc。提高性能
spark Executor内存分三块,execution内存,storage内存,other内存
一般oom在execution内存,storage内存满了会自己清除旧的。
三种情况
Driver heap OOM
从Executor端收集数据回Driver端
解决:
1能避免到Driver端做的尽量在Executor端RDD操作。
2不能避免自己评估需要内存,增加Deiver内存大小。
(*)从数据库拉到deriver的对象太大
考虑将对象转换成executor端加载sc.textFile等,加大内存解决。
map task运行溢出
增大堆内内存
增大堆外内存(默认申请的堆外内存为executor的10%)
--conf spark.executor.memoryoverhead 2048M
shuffle阶段
reduce task去map拉数据,一边拉数据一边聚合
有时报错shuffle file not found,再跑一遍就好了
增大重试次数和等待时间间隔即可
val conf = new SparkConf()
.set("spark.shuffle.io.maxRetries","6")
.set("spark.suffle.io.retryWait")
client模式driver在本地,JVM永久代为128M,而cluster模式在集群节点上默认是82M
提交时修改即可
--conf spark.driver.extraJavaOptions="-XX:PermSize=128M -xx:MaxPermSize=256M"
自解释的数据类型,自身内容包含对自身结果的描述
通常用于Impala、spark
和ORC主要区别:ORC支持ACID和update操作
hive 0.13之后支持行级别的ACID就是仅支持ORC格式
它并不是一个单纯的列式存储格式,仍然是首先根据行组分割整个表,在每一个行组内进行按列存储。ORC文件是自描述的,它的元数据使用Protocol Buffers序列化,并且文件中的数据尽可能的压缩以降低存储空间的消耗
由于OLAP查询的特点,列式存储可以提升其查询性能,但是它是如何做到的呢?这就要从列式存储的原理说起,从图1中可以看到,相对于关系数据库中通常使用的行式存储,在使用列式存储时每一列的所有元素都是顺序存储的。由此特点可以给查询带来如下的优化:
ORC、Parquet两者的对比
https://blog.csdn.net/lsr40/article/details/107975889
83023)]
tungsten 优化
使用堆外内存和新的内存管理模型。节省了内存空间和大量gc。提高性能
spark Executor内存分三块,execution内存,storage内存,other内存
一般oom在execution内存,storage内存满了会自己清除旧的。
三种情况
Driver heap OOM
从Executor端收集数据回Driver端
解决:
1能避免到Driver端做的尽量在Executor端RDD操作。
2不能避免自己评估需要内存,增加Deiver内存大小。
(*)从数据库拉到deriver的对象太大
考虑将对象转换成executor端加载sc.textFile等,加大内存解决。
map task运行溢出
增大堆内内存
增大堆外内存(默认申请的堆外内存为executor的10%)
--conf spark.executor.memoryoverhead 2048M
shuffle阶段
reduce task去map拉数据,一边拉数据一边聚合
有时报错shuffle file not found,再跑一遍就好了
增大重试次数和等待时间间隔即可
val conf = new SparkConf()
.set("spark.shuffle.io.maxRetries","6")
.set("spark.suffle.io.retryWait")
client模式driver在本地,JVM永久代为128M,而cluster模式在集群节点上默认是82M
提交时修改即可
--conf spark.driver.extraJavaOptions="-XX:PermSize=128M -xx:MaxPermSize=256M"
[外链图片转存中…(img-ArGF6qiE-1664110283024)]
[外链图片转存中…(img-usxhJ96X-1664110283025)]
自解释的数据类型,自身内容包含对自身结果的描述
通常用于Impala、spark
和ORC主要区别:ORC支持ACID和update操作
hive 0.13之后支持行级别的ACID就是仅支持ORC格式
它并不是一个单纯的列式存储格式,仍然是首先根据行组分割整个表,在每一个行组内进行按列存储。ORC文件是自描述的,它的元数据使用Protocol Buffers序列化,并且文件中的数据尽可能的压缩以降低存储空间的消耗
由于OLAP查询的特点,列式存储可以提升其查询性能,但是它是如何做到的呢?这就要从列式存储的原理说起,从图1中可以看到,相对于关系数据库中通常使用的行式存储,在使用列式存储时每一列的所有元素都是顺序存储的。由此特点可以给查询带来如下的优化:
ORC、Parquet两者的对比
https://blog.csdn.net/lsr40/article/details/107975889