自学内容网 自学内容网

Linux云计算 |【第五阶段】ARCHITECTURE-DAY3

主要内容:

了解Hadoop与大数据的关系,理解HDFS、Mapreduce、Yarn的架构、调用Hadoop执行数据分析的方法、搭建分布式Hadoop执行;

一、大数据概述

背景介绍:

随著计算机技术的发展,互联网的普及,信息的积累已经到了一个非常庞大的地步,信息的增长也在不断的加快,随着互联网、物联网建设的加快,信息更是爆炸式增长,收集、检索、统计这些信息越发困难,必须使用新的技术来解决这些问题;大数据指无法在一定时间范围内,用常规软件工具进行捕捉、管理和处理的数据集合,需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产;是指从各种各样类型的数据中,快速获得有价值的信息;

大数据(Big Data)是指在传统数据处理软件无法处理的规模、速度和复杂性下生成和收集的数据集合。大数据技术涉及从这些大规模数据集中提取有价值的信息和洞察力。

大数据的五个主要特征,通常被称为“5V”:(中级系统项目管理工程师)

  1. Volume(容量):大数据的容量非常大,通常以TB、PB甚至EB为单位。数据来源广泛,包括社交媒体、传感器、交易记录等。
  2. Velocity(速度):大数据的生成和处理速度非常快,需要实时或近实时处理。数据流可以是连续的,需要快速分析和响应。
  3. Variety(多样性):大数据的类型多样,包括结构化数据(如数据库中的表格数据)、半结构化数据(如JSON、XML)和非结构化数据(如文本、图像、音频、视频)。数据来源多样,包括社交媒体、传感器、日志文件等。
  4. Veracity(真实性):大数据的真实性和质量是一个重要问题,因为数据可能包含噪声、错误或不完整的信息。数据清洗和预处理是确保数据质量的关键步骤。
  5. Value(价值)

大数据技术在各个行业和领域都有广泛的应用,包括但不限于:商业智能、金融、医疗、零售、社交媒体

大数据技术栈:

用于数据的收集、存储、处理和分析

数据收集

  • 数据收集工具和技术用于从各种来源收集数据,如传感器、社交媒体、日志文件等。
  • 常见的工具包括Flume、Scribe、Kafka等。

数据存储

  • 大数据存储技术用于存储大规模数据,通常采用分布式存储系统。
  • 常见的存储系统包括Hadoop HDFS、Amazon S3、Google Cloud Storage等。

数据处理

  • 大数据处理技术用于处理和分析大规模数据,通常采用分布式计算框架。
  • 常见的处理框架包括Hadoop MapReduce、Spark、Flink等。

数据分析

  • 大数据分析技术用于从数据中提取有价值的信息和洞察力。
  • 常见的分析工具包括Hive、Pig、Impala、Presto等。

数据可视化

  • 数据可视化工具用于将分析结果以图形化的方式展示,帮助用户理解和解释数据。
  • 常见的可视化工具包括Tableau、Power BI、D3.js等。

1、Hadoop生态系统介绍

Hadoop是一个开源的分布式计算框架,最初由Apache基金会开发,用于处理大规模数据集。Hadoop生态系统是一个由多个组件和工具组成的集合,这些组件和工具协同工作,提供了一个完整的大数据处理解决方案。

Hadoop生态系统的优势:

  • 高可扩展性:支持水平扩展,可通过增加节点来扩展集群的存储和计算能力
  • 高容错性:HDFS和MapReduce设计了高容错机制,确保数据和计算任务的可靠性
  • 多样化的数据处理能力:提供多种数据处理工具和框架,支持批处理、实时处理、数据仓库等
  • 开源和社区支持:拥有庞大的社区支持,提供了丰富的文档、教程和第三方工具

起源:2003年开始Google发表3篇论文:GFS、MapReduce、BigTable(核心组件)

  • ① GFS是一个可扩展的分布式文件系统,用于大型的、分布式的、对大量数据进行访问的应用,可以运行于廉价的普通硬件上,提供容错功能。
  • ② MapReduce是针对分布并行计算的一套编程模型,由Map和Reduce组成,Map是映射,把指令分发到多个worker上,Reduce是规约,把worker计算出的结果合并。
  • ③ BigTable是存储结构化数据的数据库,建立在GFS、Scheduler、Lock Service和MapReduce之上。

2、Hadoop生态系统组件介绍  

1)Hadoop核心组件

① Hadoop Distributed File System (HDFS)

  • - 功能:HDFS是Hadoop的分布式文件系统,用于存储大规模数据集。
    - 特点:高容错性、高吞吐量、适合大规模数据存储。
    - 工作原理:数据被分成块并存储在多个节点上,每个块有多个副本以确保数据可靠性。

② MapReduce

  • - 功能:MapReduce是Hadoop的编程模型,用于处理和生成大规模数据集。
    - 特点:分布式计算、适合批处理任务。
    - 工作原理:数据处理任务被分成Map和Reduce两个阶段,Map阶段将数据映射成键值对,Reduce阶段对这些键值对进行汇总和处理。

HDFS集群和YARN集群,两者逻辑上分离,但物理上常在一起

2)Hadoop生态系统组件

① YARN (Yet Another Resource Negotiator)

  • 功能:YARN是Hadoop的资源管理器,用于管理和调度集群资源
  • 特点:支持多种计算框架,如MapReduce、Spark等。
  • 工作原理:YARN将资源管理和作业调度分离,提高了集群的资源利用率和灵活性。

② HBase

  • 功能:HBase是一个分布式、面向列的NoSQL数据库,构建在HDFS之上。
  • 特点:高可扩展性、高吞吐量、适合实时读写操作。
  • 应用场景:实时数据存储和查询,如日志分析、实时监控等。

③ Hive

  • 功能:Hive是一个数据仓库工具,用于查询和管理大规模数据集
  • 特点:支持SQL查询、适合批处理任务。
  • 工作原理:Hive将SQL查询转换为MapReduce任务执行。

④ Pig

  • 功能:Pig是一个高级数据流语言和执行框架,用于处理大规模数据集
  • 特点:支持脚本语言Pig Latin、适合ETL(Extract, Transform, Load)任务。
  • 工作原理:Pig将Pig Latin脚本转换为MapReduce任务执行。

⑤ Sqoop

  • 功能:Sqoop是一个用于在Hadoop和关系型数据库之间传输数据的工具
  • 特点:支持批量数据导入导出、适合数据集成任务。
  • 工作原理:Sqoop将数据从关系型数据库导入HDFS或从HDFS导出到关系型数据库。

⑥ Flume

  • 功能:Flume是一个分布式、可靠的日志收集系统
  • 特点:高吞吐量、高可靠性、适合日志数据收集。
  • 工作原理:Flume将日志数据从多个源收集并传输到HDFS或其他存储系统。

⑦ Oozie

  • 功能:Oozie是一个工作流调度系统,用于管理和调度Hadoop作业
  • 特点:支持复杂工作流、适合批处理任务。
  • 工作原理:Oozie定义和执行工作流,确保作业按顺序和依赖关系执行。

⑧ Zookeeper

  • 功能:Zookeeper是一个分布式协调服务,用于管理和协调分布式系统
  • 特点:高可用性、高可靠性、适合分布式系统管理。
  • 工作原理:Zookeeper提供分布式锁、配置管理、命名服务等功能。

HDFS(Hadoop分布式文件系统)

- HDFS是Hadoop体系中数据存储管理的基础,它是一个高度容错的系统,能检测和应对硬件故障,用于在低成本的通用硬件上运行。HDFS简化了文件的一致性模型,通过流式数据访问,提供高吞吐量应用程序数据访问功能,适合带有大型数据集的应用程序。

- HDFS采用master/slave架构,一个HDFS集群是由一个Namenode (Master)和一定数目的Datanodes (Slave)组成。

HDFS角色及架构图:

- Client:切分文件;访问HDFS;与NameNode交互,获取文件位置信息;与DataNode交互,读取和写入数据。切分块文件,每块缺省大小128MB,可以多个副本;

- NameNode:Master节点,在hadoop1.X中只有一个,管理HDFS的名称空间Namespace和数据块映射信息(fsimage),配置副本策略,处理客户端请求。

- DataNode:Slave节点,存储实际的数据,汇报存储信息给NameNode。

- SecondaryNameNode:辅助NameNode,分担其工作量;定期合并fsimage和fsedits,推送给NameNode;紧急情况下,可辅助恢复NameNode,但Secondary NameNode并非NameNode的热备。(fsimage名称空间和数据库的映射信息;fsedits数据变更日志)

Mapreduce(分布式离线计算框架)

- MapReduce是一种计算模型,用以进行大数据量的计算。其中Map对数据集上的独立元素进行指定的操作(映射),生成键-值对形式中间结果。Reduce则对中间结果中相同“键”的所有“值”进行规约,以得到最终结果。MapReduce这样的功能划分,非常适合在大量计算机组成的分布式并行环境里进行数据处理

Mapreduce角色及架构图:

- JobTracker:Master节点,只有一个,管理所有作业及作业/任务的监控、错误处理等;将任务分解成一系列任务,并分派给TaskTracker。

- TaskTracker:Slave节点,运行Map Task和Reduce Task;并与JobTracker交互,汇报任务状态。

- Map Task:解析每条数据记录,传递给用户编写的map()并执行,将输出结果写入本地磁盘(如果为map-only作业,直接写入HDFS)

- Reducer Task:从Map Task的执行结果中,远程读取输入数据,对数据进行排序,将数据按照分组传递给用户编写的reduce函数执行。

YARN(集群资源管理系统)

- YARN是Hadoop的资源管理器,它是一个通用资源管理系统和调度平台,可为上层应用提供统一的资源管理和调度,它的引入为集群在利用率、资源统一管理和数据共享等方面带来了巨大好处。

YARN架构图:

- ResourceManager(RM):是一个全局的资源管理器,负责处理客户端请求和整个系统的资源管理和调度分配。启动/监控AM,监控NM,它主要由两个组件构成:调度器(Scheduler)和应用程序管理器(ApplicationsManager,AM)

  • a) Scheduler:负责分配最少但满足ApplicationManager运行所需的资源量给ApplicationManager。Scheduler只是基于资源的使用情况进行调度,并不负责监视/跟踪application的状态,当然也不会处理失败的task。
  • b) ApplicationManager(AM):负责从Scheduler申请资源,以及跟踪这些资源的使用情况以及任务进度的监控; 负责与RM调度器协商以获取的资源用Container表示,;
  • c) Container:是YARN中对任务运行环境资源的抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当AM向RM申请资源时,RM为AM返回的资源便是用Container表示。YARN会为每个任务分配一个Container,且该任务只能使用该Container中描述的资源。(启动命令等任务运行相关的信息资源分配与调度)

- NodeManager(NM):是单个节点上的资源和任务管理器,主要负责启动RM分配给AM的container以及代表AM的container,并且会监视container的运行情况;一方面,它会定时地向RM汇报本节点上的资源使用情况(CPU、内存)和各个Container的运行状态;另一方面,它接收并处理来自AM的Container启动/停止等各种请求。

3、Hadoop的部署模式

① 单机:在一台机器上安装部署;(软件地址:Apache Hadoop

② 伪分布式:在一台机器上安装部署,但区分角色;

③ 完全分布式:多台机器上安装部署,不同角色服务安装在不同的机器上;

  • - 配置文件目录:/usr/local/hadoop/etc/hadoop
  • - 执行程序路径:/usr/local/hadoop/bin/Hadoop


单机安装Hadoop部署示例:

步骤1:采购1台云主机

主机名称

IP地址

相关配置

hadoop1

192.168.1.50

最低配置2核4G

步骤2:单机安装Hadoop

# 拷贝云盘public/hadoop/hadoop-2.7.7.tar.gz到hadoop1 上

[root@ecs-proxy ~]# scp hadoop-2.7.7.tar.gz 192.168.1.50:/root

① 安装JAVA环境及依赖

[root@hadoop1 ~]# yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel
[root@hadoop1 ~]# tar -zxf hadoop-2.7.7.tar.gz       //解压hadoop压缩包
[root@hadoop1 ~]# mv hadoop-2.7.7 /usr/local/hadoop  //解压后拷贝到/usr/local/hadoop
[root@hadoop1 ~]# chown -R 0.0 /usr/local/hadoop      //将文件权限设为root(0.0代表UID、GID)
[root@hadoop1 ~]# ls /usr/local/hadoop/

② 修改Hadoop的环境变量文件(配置JAVA环境、指定hadoop配置文件路径)

# 可通过rpm-ql命令查看安装软件包java-1.8.0-openjdk的安装路径

[root@hadoop1 ~]# rpm -ql java-1.8.0-openjdk

[root@hadoop1 ~]# vim /usr/local/hadoop/etc/hadoop/hadoop-env.sh
25:  export JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.292.b10-1.el7_9.x86_64/"   //配置JAVAh环境
33:  export HADOOP_CONF_DIR="/usr/local/hadoop/etc/hadoop"    //配置文件路径

补充:Hadoop基于JAVA开发且需使用JAVA执行,必须配置JAVA安装路径

③ 验证服务

[root@hadoop1 ~]# /usr/local/hadoop/bin/hadoop version        //查看版本

[root@hadoop1 ~]# /usr/local/hadoop/bin/hadoop --help   //查看帮助

步骤3:验证热点词汇分析

① 创建数据分析目录,并拷贝文件

[root@hadoop1 ~]# cd /usr/local/hadoop
[root@hadoop1 hadoop]# mkdir input    //创建数据分析目录
[root@hadoop1 hadoop]# cp *.txt input/  //将hadoop目录下的.txt文件拷贝
[root@hadoop1 hadoop]# ls input/
LICENSE.txt  NOTICE.txt  README.txt

② 运行jar程序,分析词汇出现次数

运行Hadoop官方的jar程序文件,通过wordconut算法对input目录下的所有文件进行词汇出现次数分析统计,并将统计结果输出给output分析输出目录

[root@hadoop1 hadoop]# ./bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.7.jar wordcount ./input ./output
[root@hadoop1 hadoop]# ls ./output/
part-r-00000  _SUCCESS
[root@hadoop1 hadoop]# cat ./output/part-r-00000     //对词汇出现的次数统计


集群安装Hadoop部署示例:

HDFS、Mapreduce、YARN

1、HDFS分布式文件系统

- HDFS规划架构图:

步骤1:购买4台云主机

主机名称

IP地址

相关配置

角色

备注

hadpoo1

192.168.1.50

最低配置2核4G

NameNode

SecondaryNamenode

HDFS

node-0001

192.168.1.51

最低配置2核4G

DateNode

HDFS

node-0002

192.168.1.52

最低配置2核4G

DateNode

HDFS

node-0003

192.168.1.53

最低配置2核4G

DateNode

HDFS

提示:镜像模板已禁用SELinux和Firewalld,未禁用主机需提前设置;

步骤2:HDFS集群-环境准备

① 配置SSH免密登录(hadpoo1操作)

注意:Hadoop是远程在其它节点上启动角色,所以每台主机都要能免密登录,包括本机!

补充:第一次使用SSH登录远程主机时需输入Yes,可能造成主机不能继续执行,禁用ssh key检测;

[root@hadoop1 ~]# vim /etc/ssh/ssh_config
60:  StrictHostKeyChecking no     //禁用ssh key检测
[root@hadoop1 ~]# ssh-keygen -t rsa -b 2048 -N '' -f /root/.ssh/id_rsa
[root@hadoop1 ~]# for i in {50..53}
> do
> ssh-copy-id 192.168.1.$i
> done

② 配置主机名解析(hadoop1、node-0001、node-0002、node-0003操作)

Hadoop非常依赖主机名解析,如果配置DNS解析需要正向解析和方向解析,实验中使用/etc/hosts文件来解析主机名

[root@hadoop1 ~]# vim /etc/hosts
192.168.1.50   hadoop1
192.168.1.51   node-0001
192.168.1.52   node-0002
192.168.1.53   node-0003
[root@hadoop1 ~]# for i in hadoop1 node-{0001..0003}
> do
> scp /etc/hosts $i:/etc/hosts
> done

③ 为所有节点安装JAVA环境(hadoop1、node-0001、node-0002、node-0003操作)

[root@hadoop1 ~]# for i in hadoop1 node-{0001..0003}
> do
> ssh $i "yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel"
> done

步骤3:HDFS集群-配置部署

参考:public/hadoop/hadoop-2.7.7.tar.gz

1)HDFS配置文件目录(/usr/local/hadoop/etc/hadoop/*)

  • - 环境配置文件:hadoop-env.sh
  • - 核心配置文件:core-site.xml
  • - HDFS配置文件:hdfs-site.xml
  • - 节点配置文件:slaves
[root@hadoop1 ~]# ls /usr/local/hadoop/etc/hadoop/

补充:XML语法格式

- XML指可扩展标记语言(Extensible Markup Language)

- XML中的每个元素名都是成对出现,结束标签需加【/】

例如:Hadoop配置语法

配置文件语法格式:[官方手册](Hadoop – Apache Hadoop 2.7.7)

① 配置环境配置文件(hadoop-env.sh),配置JAVA运行环境

# 可通过rpm-ql命令查看安装软件包java-1.8.0-openjdk的安装路径

[root@hadoop1 ~]# vim /usr/local/hadoop/etc/hadoop/hadoop-env.sh
25:  export JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.292.b10-1.el7_9.x86_64/"
33:  export HADOOP_CONF_DIR="/usr/local/hadoop/etc/hadoop"

② 配置节点配置文件(slaves)—> 部署Datenode

- slaves是DataNode节点的配置文件,声明的主机都会运行DataNode守护进程;

注意:slave配置文件格式,每行写一个主机名,主机名必须保证能ping通(localhost必须删除)

[root@hadoop1 ~]# vim /usr/local/hadoop/etc/hadoop/slaves
node-0001
node-0002
node-0003

③ 配置核心配置文件(core-site.xml)

[root@hadoop1 ~]# vim /usr/local/hadoop/etc/hadoop/core-site.xml
<configuration>
    <property>
        <name>fs.defaultFS</name>    //文件系统配置参数
        <value>hdfs://hadoop1:9000</value>    //指定HDFS文件系统
    </property>
    <property>
        <name>hadoop.tmp.dir</name>    //数据目录配置参数
        <value>/var/hadoop</value>     //定义数据存放目录
    </property>
</configuration>

④ 配置HDFS配置文件(hdfs-site.xml)—> 部署namenode,Secondarynamenode

[root@hadoop1 ~]# vim /usr/local/hadoop/etc/hadoop/hdfs-site.xml
<configuration>
    <property>
        <name>dfs.namenode.http-address</name>   //声明Namenode地址
        <value>hadoop1:50070</value>   //主机名:端口号,用来通信
    </property>
    <property>
        <name>dfs.namenode.secondary.http-address</name>   //声明Secondarynamenode地址
        <value>hadoop1:50090</value>   //主机名:端口号,用来通信
    </property>
    <property>
        <name>dfs.replication</name>   //定义副本数量
        <value>2</value>
    </property>
</configuration>

⑤ 同步配置文件目录到其它主机

- HDFS集群要求所有节点配置文件都必须相同

[root@hadoop1 ~]# for i in node-{0001..0003}
> do
> rsync -aXSH --delete /usr/local/hadoop ${i}:/usr/local/
> done

⑥ 创建数据存放目录

- 只在namenode上创建即可,其它datanode主机可自动创建

[root@hadoop1 ~]# mkdir /var/hadoop    //创建数据存放目录(core-site.xml指定)

⑦ 格式化HDFS集群(仅NameNode操作)

[root@hadoop1 ~]# /usr/local/hadoop/bin/hdfs namenode -format

补充:格式化本质是给每个存储节点分配ID,格式化只能做一次;如果格式化多次,会报错ID冲突,解决方法:首先停止集群./sbin/stop-dfs.sh,删除所有节点的数据目录配置创建的dfs目录结构rm-rf /var/Hadoop/*

⑧ 启动集群(仅NameNode操作)

[root@hadoop1 ~]# /usr/local/hadoop/sbin/start-dfs.sh

⑨ 验证角色

[root@hadoop1 ~]# for i in hadoop1 node-{0001..0003}
> do
> echo ${i};
> ssh ${i} jps;
> echo -e "\n";
> done

补充:jps(Java Virtual Machine Process Status Tool)是java提供的一个显示当前所有java进程pid的命令,适合在linux/unix平台上简单查看当前java进程的一些简单情况。

⑩ 验证集群

[root@hadoop1 ~]# /usr/local/hadoop/bin/hdfs dfsadmin -report

日志与排错

- 日志文件夹在系统启动时会被自动创建:/usr/local/hadoop/logs

- 日志名称:

  • 服务名-用户名-角色名-主机名.out   //标准输出
  • 服务名-用户名-角色名-主机名.log   //日志信息
[root@hadoop1 ~]# ls /usr/local/hadoop/logs/

 


2、Mapreduce分布式离线计算框架:

计算框架有多种,例如:Mapreduce、storm、spark,一般由开发人员根据企业需求编写;

实验使用官方提供的模板案例:mapred-site.xml.template

① 配置计算框架配置文件mapred-site.xml文件

[root@hadoop1 ~]# cd /usr/local/hadoop/etc/hadoop/
[root@hadoop1 hadoop]# cp mapred-site.xml.template mapred-site.xml
[root@hadoop1 hadoop]# vim mapred-site.xml
<configuration>
    <property>
        <name>mapreduce.framework.name</name>  //配置使用YRAN的资源管理类
        <value>yarn</value>
    </property>
</configuration>


3、YARN集群资源管理系统

YARN规划架构图:

主机名称

IP地址

相关配置

角色

备注

hadpoo1

192.168.1.50

最低配置2核4G

NameNode

SecondaryNamenode

ResourceManager

HDFS

YARN

node-0001

192.168.1.51

最低配置2核4G

DateNode

NodeManager

HDFS

YARN

node-0002

192.168.1.52

最低配置2核4G

DateNode

NodeManager

HDFS

YARN

node-0003

192.168.1.53

最低配置2核4G

DateNode

NodeManager

HDFS

YARN

步骤1:

① 配置资源管理配置文件yarn-site.xml文件

[root@hadoop1 ~]# vim /usr/local/hadoop/etc/hadoop/yarn-site.xml
<configuration>
    <property>
        <name>yarn.resourcemanager.hostname</name>   //全局资源管理主机(resourcemanager)
        <value>hadoop1</value>
    </property>
<!-- Site specific YARN configuration properties -->
    <property>
        <name>yarn.nodemanager.aux-services</name>   //计算框架(nodemanager)
        <value>mapreduce_shuffle</value>
    </property>
</configuration>

② 同步配置文件目录到其它主机

[root@hadoop1 ~]# for i in node-{0001..0003}
> do
> rsync -avXSH --delete /usr/local/hadoop/  ${i}:/usr/local/hadoop/
> done

③ 启动集群

[root@hadoop1 ~]# /usr/local/hadoop/sbin/start-yarn.sh

④ 验证角色

[root@hadoop1 ~]# for i in hadoop1 node-{0001..0003}
> do
> echo ${i};
> ssh ${i} jps;
> echo -e "\n";
> done

⑤ 验证集群

[root@hadoop1 ~]# /usr/local/hadoop/bin/yarn node -list

⑥ WEB页面访问

# 使用华为云给Hadoop1绑定弹性公网IP(例如:124.71.115.1)

(1)NameNode:http://hadoop1:50070

(2)SecondaryNamenode:http://hadoop1:50090

(3)ResourceManager:http://hadoop1:8088/cluster

(4)DataNode:http://node-0001:50075

(5)NodeManager:http://node-0001:8042/node

小结:

本篇章节为【第五阶段】ARCHITECTURE-DAY3 的学习笔记,这篇笔记可以初步 了解Hadoop与大数据的关系,理解HDFS、Mapreduce、Yarn的架构、调用Hadoop执行数据分析的方法、搭建分布式Hadoop执行,除此之外推荐参考相关学习网址:


Tip:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解。
 


原文地址:https://blog.csdn.net/AnJern/article/details/142988315

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!