0


拜托!看了这一篇谁还不会Spark!!!

一、Hadoop基本认知

Hadoop是一个分布式系统基础技术框架,由Apache基金会所开发。利用Hadoop,软件开发用户可以在不了解分布式底层细节的情况下,开发分布式程序,从而达到充分利用集群的威力高速运算和存储的目的。

Hadoop

Hadoop的框架核心组建主要包括HDFS、MapReduce和YARN。

HDFS(Hadoop Distributed File System):即分布式文件系统,是Hadoop的基础组件之一。它主要负责集群数据的存储与读取,采用主/从(Master/Slave)体系结构的分布式文件系统,支持传统的层次型文件组织结构,并具有高容错性和适合大数据处理的特点。

MapReduce:是Hadoop的核心计算框架,适用于大规模数据集(大于1TB)的并行运算。它包括Map(映射)和Reduce(规约)两部分,能够将数据转换为键值对形式,并进行分布式处理。

YARN(Yet Another Resource Negotiator):YARN是一个通用资源管理系统,为上层应用提供统一的资源管理和调度。它的引入在集群利用率、资源统一管理和数据共享等方面具有重大意义。

其次,Hadoop还有其他的组件:

1.hive(基于hadoop的数据仓库)

由Facebook开源,最初用于解决海量结构化的日志数据统计问题。hive定于了一种类似sql的查询语言(hql)将sql转化为mapreduce任务在hadoop上执行。

2.hbase(分布式列存数据库)

hbase是一个针对结构化数据的可伸缩,高可靠,高性能,分布式和面向列的动态模式数据库。和传统关系型数据库不同,hbase采用了bigtable的数据模型:增强了稀疏排序映射表(key/value)。其中,键由行关键字,列关键字和时间戳构成,hbase提供了对大规模数据的随机,实时读写访问,同时,hbase中保存的数据可以使用mapreduce来处理,它将数据存储和并行计算完美结合在一起。

3.zookeeper(分布式协作服务)

解决分布式环境下的数据管理问题:统一命名,状态同步,集群管理,配置同步等。

4.sqoop(数据同步工具)

sqoop是sql-to-hadoop的缩写,主要用于传统数据库和hadoop之间传输数据。数据的导入和导出本质上是mapreduce程序,充分利用了MR的并行化和容错性。

5.pig(基于hadoop的数据流系统)

定义了一种数据流语言-pig latin,将脚本转换为mapreduce任务在hadoop上执行。通常用于离线分析。

6.mahout(数据挖掘算法库)

mahout的主要目标是创建一些可扩展的机器学习领域经典算法的实现。mahout现在已经包含了聚类,分类,推荐引擎(协同过滤)和频繁集挖掘等广泛使用的数据挖掘方法。除了算法是,mahout还包含了数据的输入/输出工具,与其他存储系统(如数据库,mongoDB或Cassandra)集成等数据挖掘支持架构。

7.flume(日志收集工具)

cloudera开源的日志收集系统,具有分布式,高可靠,高容错,易于定制和扩展的特点。他将数据从产生,传输,处理并写入目标的路径的过程抽象为数据流,在具体的数据流中,数据源支持在flume中定制数据发送方,从而支持收集各种不同协议数据。

二、介绍mapreduce

1.mapreduce的定义

MapReduce是Hadoop生态中的一个分布式计算框架。通过使用它,开发人员不必关心分布式计算底层怎么去实现,只需关心相应的业务逻辑,就可以轻松地编写应用程序,以可靠、容错的方式并行处理大型硬件集群上的大量数据集。

2.mapreduce的优缺点:

2.1. 优点:

1.易于编程。用户只关系业务逻辑,实现框架的接口;

2.良好的扩展性。可以动态的增加服务器,解决计算资源不够的问题;

3.高容错性。任何一台机器挂掉,可以将任务转移到其他节点;

4.适合海量数据的计算(TB/PB),几千台服务器共同计算。

2.2. 缺点:

1.不擅长实时计算,毫秒,秒级别的计算;

2.不擅长流式计算;

3.不擅长DAG有向无环图计算

3.mapreduce的核心思想

4.mapreduce的进程

一个完整的MapReduce程序在分布式运行时有三类实例进程:

1.MrAppMaster:负责整个程序的过程调度及状态协调

2.MapTask:负责Map阶段的整个数据处理流程

3.ReduceTask:负责Reduce阶段的整个数据处理流程

三、介绍****spark

1.简单介绍spark

Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。

Spark,拥有Hadoop MapReduce所具有的优点;但不同于MapReduce的是--Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapReduce的算法。

Spark 是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同之处,Spark 启用了内存分布数据集,除了能够提供交互式查询外,它还可以优化迭代工作负载。

Spark 是在 Scala 语言中实现的,它将 Scala 用作其应用程序框架。与 Hadoop 不同,Spark 和Scala 能够紧密集成,其中的 Scala 可以像操作本地集合对象一样轻松地操作分布式数据集。

2.spark的特点:

2.1快速:与Hadoop的MapReduce相比,Spark基于内存的运算要快100倍以上,基于硬盘的运算也要快10倍以上。Spark实现了高效的DAG执行引擎,可以通过基于内存来高效处理数据流。

2.2 易用: Spark支持Java、Python和Scala的API,还支持超过80种高级算法,使用户可以快速构建不同的应用。而且Spark支持交互式的Python和Scala的shell,可以非常方便地在这些shell中使用Spark集群来验证解决问题的方法。

2.3 通用:Spark提供了统一的解决方案。Spark可以用于批处理、交互式查询(Spark SQL)、实时流处理(Spark Streaming)、机器学习(Spark MLlib)和图计算(GraphX)。这些不同类型的处理都可以在同一个应用中无缝使用。Spark统一的解决方案非常具有吸引力,毕竟任何公司都想用统一的平台去处理遇到的问题,减少开发和维护的人力成本和部署平台的物力成本。

2.4 随处运行:用户可以使用spark的独立集群模式运行spark,也可以在亚马逊弹性计算云、Hadoop YARN资源管理器或Apache Mesos上运行spark。spark作为一个分布式计算框架,本身并没有存储功能,但是spark可以从HDFS、Cassandra、HBases、Hive、Alluxii等数据源中欧读取数据。

2.5 代码简洁:spark支持使用Scala、Python等语言编写代码。Scala和Python的代码相对Java的代码而言比较简洁,因此,在Spark中一般都使用Scala或Python编写应用程序,这也比在MapReduce中编写应用程序简单方便。

3.Spark的运行架构

(1)客户端:用户提交作业的客户端

(2)Driver:负责运行应用程序(Application)的main函数并创建SparkContext,应用程序包含Driver功能的代码和分布在集群中多个节点上的Executor代码。

(3)SparkContext:应用上下文,控制整个生命周期。

(4)Cluster Manager:资源管理器,即在集群上获取资源的外部服务,目前主要有Standalone和YARN:

    (1)Standalone是Spark原生的资源管理器,由Master进程负责资源的分配,也可以理解为使用Standalone时Cluster Manager是Master进程所在节点。

  (2)YARN是Hadoop集群的资源管理器,若使用YARN作为Spark程序运行的资源管理器,则由ResourceManager负责资源的分配

(5)Spark Worker:集群中任何可以运行应用程序的节点,运行一个或多个Executor进程。

(6)Executor:运行在Spark Worker上的任务(Task)执行器,Executor启动线程池运行Task,并负责将数据存在内存或磁盘上,每个应用程序都会申请各自的Executor以处理任务。

(7)Task:被发送都某个Executor的具体任务。

4.Spark运行模式

Spark 有多种运行模式,Spark 支持本地运行模式(Local 模式)、独立运行模式(Standalone 模式)、Mesos、YARN(Yet Another Resource Negotiator)、Kubernetes 模式等。

本地运行模式是 Spark 中最简单的一种模式,也可称作伪分布式模式。

独立运行模式为 Spark 自带的一种集群管理模式,Mesos 及 YARN 两种模式也是比较常用的集群管理模式。相比较 Mesos 及 YARN 两种模式而言,独立运行模式是最简单,也最容易部署的一种集群运行模式。

Kubernetes 是一个用于自动化部署、扩展和管理容器化应用程序的开源系统。

Spark 底层还支持多种数据源,能够从其它文件系统读取数据,如 HDFS、Amazon S3、Hypertable、HBase 等。Spark 对这些文件系统的支持,同时也丰富了整个 Spark 生态的运行环境。

5.Spark 部署模式

Spark 支持多种分布式部署模式,主要支持三种部署模式,分别是:StandaloneSpark on YARNSpark on Mesos模式。

Standalone模式为 Spark 自带的一种集群管理模式,即独立模式,自带完整的服务,可单独部署到一个集群中,无需依赖任何其他资源管理系统。它是 Spark 实现的资源调度框架,其主要的节点有 Driver 节点、Master 节点和 Worker 节点。Standalone模式也是最简单最容易部署的一种模式。

Spark on YARN模式即 Spark 运行在Hadoop YARN框架之上的一种模式。Hadoop YARN(Yet Another Resource Negotiator,另一种资源协调者)是一种新的 Hadoop 资源管理器,它是一个通用资源管理系统,可为上层应用提供统一的资源管理和调度。

Spark on Mesos模式,即 Spark 运行在Apache Mesos框架之上的一种模式。Apache Mesos是一个更强大的分布式资源管理框架,负责集群资源的分配,它允许多种不同的框架部署在其上,包括YARN。它被称为是分布式系统的内核。

四、mapreduce和spark的区别

1、Spark处理数据是基于内存的,而MapReduce是基于磁盘处理数据的

MapReduce是将中间结果保存到磁盘中,减少了内存占用,牺牲了计算性能。

Spark是将计算的中间结果保存到内存中,可以反复利用,提高了处理数据的性能。

2、Spark在处理数据时构建了DAG有向无环图,减少了shuffle和数据落地磁盘的次数

Spark计算比MapReduce快的根本原因在于DAG计算模型。一般而言,DAG相比MapReduce在大多数情况下可以减少shuffle次数。Spark的DAGScheduler相当于一个改进版的MapReduce,如果计算不涉及与其他节点进行数据交换,Spark可以在内存中一次性完成这些操作,也就是中间结果无须落盘,减少了磁盘IO的操作。但是,如果计算过程中涉及数据交换,Spark也是会把shuffle的数据写磁盘的。

3、Spark比MapReduce快

有一个误区,Spark是基于内存的计算,所以快,这不是主要原因,要对数据做计算,必然得加载到内存,Hadoop也是如此,只不过Spark支持将需要反复用到的数据Cache到内存中,减少数据加载耗时,所以Spark跑机器学习算法比较在行(需要对数据进行反复迭代)。

4、Spark是粗粒度资源申请,而MapReduce是细粒度资源申请

粗粒度申请资源指的是在提交资源时,Spark会提前向资源管理器(YARN,Mess)将资源申请完毕,如果申请不到资源就等待,如果申请到就运行task任务,而不需要task再去申请资源。

MapReduce是细粒度申请资源,提交任务,task自己申请资源自己运行程序,自己释放资源,虽然资源能够充分利用,但是这样任务运行的很慢。

5、MapReduce的Task的执行单元是进程,Spark的Task执行单元是线程

进程的创建销毁的开销较大,线程开销较小。

6、Spark优缺点

优点:

1)Spark把中间数据放到内存中,迭代运算效率高。

Spark支持DAG图的分布式并行计算的编程框架,减少了迭代过程中数据的落地,提高了处理效率。

2)Spark 容错性高

Spark 引进了弹性分布式数据集 RDD (Resilient DistributedDataset) 的抽象,它是分布在一组节点中的只读对象集合,这些集合是弹性的,如果数据集一部分丢失,则可以根据“血统”(即允许基于数据衍生过程)对它们进行重建。另外在RDD 计算时可以通过 CheckPoint 来实现容错。

3)Spark更加通用

Spark提供的数据集操作类型分为:Transformations和Actions两大类。Transformations包括Map、Filter、FlatMap、Sample、GroupByKey、ReduceByKey、Union、Join、Cogroup、MapValues、Sort等多种操作类型,同时还提供Count, Actions包括Collect、Reduce、Lookup和Save等操作。

缺点:

1)内存问题

JVM的内存overhead太大,1G的数据通常需要消耗5G的内存。

2)性能问题

由于大量数据抄被缓存在RAM中,Java回收垃圾缓慢的情况严重,导致Spark性能不稳定。

7、MapReduce优缺点

优点:

1)MapReduce 易于编程

它简单的实现一些接口,就可以完成一个分布式程序,这个分布式程序可以分布到大量廉价的 PC 机器上运行。也就是说你写一个分布式程序,跟写一个简单的串行程序是一模一样的。就是因为这个特点使得 MapReduce 编程变得非常流行。

2)良好的扩展性

当你的计算资源不能得到满足的时候,你可以通过简单的增加机器来扩展它的计算能力。

3)高容错性

MapReduce 设计的初衷就是使程序能够部署在廉价的 PC 机器上,这就要求它具有很高的容错性。比如其中一台机器挂了,它可以把上面的计算任务转移到另外一个节点上运行, 不至于这个任务运行失败,而且这个过程不需要人工参与,而完全是由Hadoop内部完成的。

4)适合 PB 级以上海量数据的离线处理

可以实现上千台服务器集群并发工作,提供数据处理能力。

缺点:

1)不擅长实时计算

MapReduce无法像MySQL一样,在毫秒或者秒级内返回结果。

2)不擅长流式计算

流式计算的输入数据是动态的,而MapReduce的输入数据集是静态的,不能动态变化。这是因为 MapReduce 自身的设计特点决定了数据源必须是静态的。

3)不擅长 DAG(有向无环图)计算

多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出。在这种情况下,MapReduce并不是不能做,而是使用后,每个MapReduce作业的输出结果都会写入到磁盘, 会造成大量的磁盘 IO,导致性能非常的低下。

五、结构化数据与非结构化数据

1.结构化数据

结构化的数据是指可以使用关系型数据库表示和存储,表现为二维形式的数据。
一般特点是:数据以行为单位,一行数据表示一个实体的信息,每一行数据的属性是相同的。如mysql数据库中的数据、csv文件

2.非结构化数据

非结构化数据是指信息没有一个预先定义好的数据模型或者没有以一个预先定义的方式来组织。非结构化数据一般指大家文字型数据,但是数据中有很多诸如时间,数字等的信息。相对于传统的在数据库中或者标记好的文件,如文本、图片、音频/视频信息等等。

六、Linux简单操作命令实训练习

1. pwd 命令
格式:pwd
功能:显示当前所在目录(即工作目录)。

2. ls 命令
格式:ls [选项] [文件|目录]
功能:显示指定目录中的文件或子目录信息。当不指定文件或目录时,显示
当前工作目录中的文件或子目录信息。
命令常用选项如下:
-a :全部的档案,连同隐藏档( 开头为 . 的档案) 一起列出来。
-l :长格式显示,包含文件和目录的详细信息。
-R :连同子目录内容一起列出来。
说明:命令“ls –l”设置了别名:ll,即输入 ll 命令,执行的是 ls –l
命令。


3.cd 命令
格式:cd <路径>
功能:用于切换当前用户所在的工作目录,其中路径可以是绝对路径也可以
是相对路径。

4.mkdir 命令
格式: mkdir [选项] 目录
功能:用于创建目录。创建目录前需保证当前用户对当前路径有修改的权
限。参数 -p 用于创建多级文件夹。

5.rm 命令
格式: rm [选项] <文件>
功能:用于删除文件或目录,常用选项-r -f,-r 表示删除目录,也可以用于
删除文件,-f 表示强制删除,不需要确认。删除文件前需保证当前用户对当
前路径有修改的权限。
图片 下载 桌面
[root@kobe ~]# rm -rf /test/
6.cp 命令
格式: cp [选项] <文件> <目标文件>
功能:复制文件或目录。
[root@localhost ~]# cp /etc/profile ./
[root@localhost ~]# ls
anaconda-ks.cfg profile test
7.mv 命令
格式:mv [选项] <文件> <目标文件>
功能:移动文件或对其改名。常用选项-i -f -b,-i 表示若存在同名文件,则向用户
询问是否覆盖;-f 直接覆盖已有文件,不进行任何提示;-b 当文件存在时,覆盖
前为其创建一个备份。

8.cat 命令
格式:cat [选项] [文件]
功能:查看文件内容。常用选项:-n 显示行号(空行也编号)。

9.tar 命令
格式:tar [选项] [档案名] [文件或目录]
功能:为文件和目录创建档案。利用 tar 命令,可以把一大堆的文件和目录
全部打包成一个文件,这对于备份文件或将几个文件组合成为一个文件以便
于网络传输是非常有用的。该命令还可以反过来,将档案文件中的文件和目
录释放出来。
常用选项:
-c 建立新的备份文件。
-C <目录> 切换工作目录,先进入指定目录再执行压缩/解压缩操作,可用于
仅压缩特定目录里的内容或解压缩到特定目录。
-x 从归档文件中提取文件。
-z 通过 gzip 指令压缩/解压缩文件,文件名为*.tar.gz。
-f<备份文件> 指定备份文件。
-v 显示命令执行过程。

10.useradd 命令
格式:useradd 用户名
功能:创建新用户,该命令只能由 root 用户使用。

11.passwd 命令
格式:passwd 用户名
功能:设置或修改指定用户的口令。

12.chown 命令
格式:chown [选项]
功能:将文件或目录的拥有者改为指定的用户或组,用户可以是用户名或者
用户 ID,组可以是组名或者组 ID,文件是以空格分开的要改变权限的文件
列表支持通配符。选项“-R”表示对目前目录下的所有文件与子目录进行相同
的拥有者变更。

chmod 命令
格式:chmod [-R] 模式 文件或目录
功能:修改文件或目录的访问权限。选项“-R”表示递归设置指定目录下的所
有文件和目录的权限。
模式为文件或目录的权限表示,有三种表示方法。
(1) 数字表示
用 3 个数字表示文件或目录的权限,第 1 个数字表示所有者的权限,第 2个
数字表示与所有者同组用户的权限,第 3 个数字表示其他用户的权限。每类
用户都有 3 类权限:读、写、执行,对应的数字分别是 4、2、1。一个用户
的权限数字表示为三类权限的数字之和,如一个用户对 A 文件拥有读写权
限,则这个用户的权限数字为 6(4+2=6)。
示例:

(2)字符赋值
用字符 u 表示所有者,用字符 g 表示与所有者同组用户,用字符 o 表示其他
用户。用字符 r、w、x 分别表示读、写、执行权限。用等号“=”来给用户赋
权限。
示例:

(3)字符加减权限
用字符 u 表示所有者,用字符 g 表示与所有者同组用户,用字符 o 表示其他
用户。用字符 r、w、x 分别表示读、写、执行权限。用加号“+”来给用户加
权限,加号“-”来给用户减权限。
示例:

13.su 命令
格式:su [-] 用户名
功能:将当前操作员的身份切换到指定用户。如果使用选项“-”,则用户切换
后使用新用户的环境变量,否则环境变量不变。
14.vi命令
格式:vi [文件名]
功能:vi 是 Linux 的常用文本编辑器,vim 是从 vi 发展出来的一个文本编辑器,
其在代码补全、编译等方便的功能特别丰富,在程序员中被广泛使用。
vi/vim 有三个工作模式:
1.命令模式
用户刚刚启动 vi/vim,便进入了命令模式。此状态下敲击键盘动作会被 vi
识别为命令,而非输入字符。以下是常用的几个命令:
i 切换到输入模式,以输入字符。
x 删除当前光标所在处的字符。
: 切换到末行模式,用以在最底一行输入命令
[root@kobe ~]# cd test
[root@kobe test]# vi profile
之后输入 i、x 或:会有相应的效果
2.输入模式
在输入模式下可以对文件执行写操作,编写完成后按 Esc 键即可返回命令模式。
3.末行模式
如果要保存、查找或者替换一些内容等,就需要进入末行模式。以下是常用的几个命
令:
Set nu:每一行显示行号
r 文件名:读取指定的文件。
w 文件名:将编辑内容保存到指定的文件内。
q:退出 vi
wq:保存文件并退出 vi
q!:强制退出 vi,不管是否保存文档内容。
15.clear 命令
格式:clear
功能:清除屏幕。实质上只是让终端显示页向后翻了一页,如果向上滚动屏
幕还可以看到之前的操作信息。
root@kobe test]# clear
16.hostname 命令
格式:hostname [选项]
功能:用于显示和设置系统的主机名称。在使用 hostname 命令设置主机名
后,系统并不会永久保存新的主机名,重新启动机器之后还是原来的主机
名。如果需要永久修改主机名,需要同时修改/etc/hostname 的相关内容。
常用选项:
-a 显示主机别名,-i 显示主机的 ip 地址。

17.hostnamectl 命令
格式 1:hostnamectl
功能:显示当前主机的名称和系统版本。
格式 2:hostnamectl set-hostname
功能:永久设置当前主机的名称。
示例:

18.ip 命令
CentOS 7 已不使用 ifconfig 命令,其功能可通过 ip 命令代替。
格式 1:ip link <命令选项> dev <设备名>
功能:对网络设备(网卡)进行操作,选项 add、delete、show、set 分别对
应增加、删除、查看和设置网络设备。
示例:IP

格式 2:ip address <命令选项> dev <设备名>
功能:对网卡的网络协议地址(IPv4/IPv6)进行操作,选项 add、change、
del、show 分别对应增加、修改、删除、查看 IP 地址。
示例: #这里将 address 缩写为 addr

19.systemctl 命令
格式:systemctl <命令选项> service_name.service
功能:管理系统中的服务,“.service”表示管理的服务均包含了一个
以 .service 结尾的文件,存放于 /lib/systemd/目录中,可以省略。命令选项
有 start、restart、reload、stop、status,分别对应服务的启动、重启、重
新加载、停止和显示状态。另外选项 enable 表示开机时启动,disable 表示
撤销开机启动。
示例:
#启动网络服务
[root@master ~]# systemctl start network
#关闭防火墙,注意 CentOS 7 的防火墙服务名称改为 firewalld
[root@master ~]# systemctl stop firewalld
#查看 ssh 服务的状态
[root@master ~]# systemctl status sshd
#设置 ssh 服务开机启动
[root@master ~]# systemctl enable sshd
20.reboot 命令
格式: reboot
功能:用于重新启动计算机,但是机器重启必须要 root 用户才有权限。
注意:本操作无需在平台系统执行
[root@master ~]# reboot
21.poweroff 命令
格式:poweroff
功能:用来关闭计算机操作系统并且切断系统电源。如果确认系统中已经没
有用户存在且所有数据都已保存,需要立即关闭系统,可以使用 poweroff
命令。
注意:本操作无需在平台系统执行
[root@master ~]# poweroff
22.export 命令
格式:export [选项] [变量名]
功能:用于将 Shell 变量输出为环境变量,或者将 Shell 函数输出为环境变
量。一个变量创建时,它不会自动地为在它之后创建的 Shell进程所知,而
命令export 可以向后面的 Shell 传递变量的值。当一个Shell 脚本调用并执行
时,它不会自动得到父脚本(调用者)里定义的变量的访问权,除非这些变
量已经被显式地设置为可用。export 命令可以用于传递一个或多个变量的值
到任何子脚本。
常用选项:
-f 代表[变量名称]中为函数名称。
-n 删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行
环境中。
-p 列出所有的 Shell 赋予程序的环境变量。
示例:
[root@master ~]# export -p #列出当前所有的环境变量
[root@master ~]# export MYENV=8 #定义环境变量,并赋值 MYENV=8
23.echo 命令
格式:echo [字符串]
功能:用于在终端设备上输出字符串或变量提取后的值。一般使用在变量前
加上符号的方式提取出变量的值,例如: 符号的方式提取出变量的值,例如:符号的方式提取出变量的值,例如:PATH然后再用 echo 命令予以
出。
示例:
#输出一段字符串 LinuxCool.com
[root@master ~]# echo “LinuxCool.com”
LinuxCool.com
#输出变量 PATH 值
[root@master ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
24.source 命令
格式:source [文件]
功能:用于重新执行刚修改的初始化文件,使之立即生效,而不必注销用
户,重新登录。
示例: #读取和执行/etc/profile 文件
[root@master ~]# source /etc/profile


本文转载自: https://blog.csdn.net/2201_75803223/article/details/136536406
版权归原作者 4k. 所有, 如有侵权,请联系我们删除。

“拜托!看了这一篇谁还不会Spark!!!”的评论:

还没有评论