您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

ElasticSearch 的概念解析与使用方式

时间:2023-12-29 14:56:40  来源:  作者:古明地觉的编程教室

ElasticSearch(后续简称 ES)在企业中的使用可以说是非常广泛了,那么 ES 到底是什么呢?我们学习 ES 能做到哪些事情呢?接下来我将用几篇文章详细聊一聊 ES。

ES 是一款高性能的分布式搜索引擎,当然里面出现的高性能、分布式已经是见怪不怪了,因此我们的重点是在搜索引擎上面。提到搜索引擎肯定不陌生,像百度、谷歌,它们都提供了自己的搜索引擎,我们每天都会在上面查找各种各样的信息。

因此:通过输入指定的关键字(关键词)来获取与之相关的信息,这个过程称之为搜索。并且搜索是不分场合的,除了百度、谷歌提供的搜索引擎之外,我们还可以在各种 App 上搜索,比如你在京东 app 上输入小提琴,那么点击确认之后会给你返回与小提琴有关的商品信息,这也是搜索。

而支持搜索的工具便是搜索引擎,它负责根据用户输入的关键字匹配出与之相关的信息,然后返回给用户,所以搜索引擎就是支持用户搜索的一个工具。

那么都有哪些工具支持搜索呢,其实说白了只要是支持字符串匹配的都可以,但能否满足不同的业务场景、以及保证高级别的搜索效率就两说了。

 

使用数据库做搜索

 

 

显然数据库是支持搜索的,毕竟它是专门用来存储数据的,其中也包含了数据分析。比如数据库中有一张表负责存储商品信息,我要查询里面所有名字包含 "洗发水" 的商品对应的 id,那么就可以这么做:

SELECT product_id FROM product 
WHERE product_name LIKE '%洗发水%';

很明显这么做是正确的,但是要拿数据库来做搜索引擎则是不合适的。因为由于业务场景的不同,会带来两个问题:

  • 假设一个商品的名称不是 "...洗发水...",而是 "...洗发液...",这个时候该商品就选不到了,但它也是需要被选出来的;再比如用户想搜索 "榨汁机",但是不小心输成了 "榨汁鸡",这个时候也没办法搜索。所以这种情况下,无法通过对关键词进行切分,来获取更多的结果。
  • 如果我们不是按商品名称、而是按商品描述进行搜索,那么还会产生效率上的问题。因为某些字段的内容会非常长,数千甚至上万个字符也是很常见的,这个时候要查询内部是否包含关键词所需要扫描的文本量就会非常大,并且该字段的每一行记录都需要扫描。如果一张表里面有千万条记录,那么这个耗时会非常恐怖。

因此用数据库实现搜索是不靠谱的,性能会非常差。

 

ElasticSearch 的概念解析与使用方式全文检索和 Lucene

 

 

既然数据库不适合专门用于搜索,那什么工具适合呢?当然是我们要聊的 ES。只不过在具体介绍 ES 之前,我们需要先说一下什么是全文检索,以及 Lucene。

首先全文检索(或者说全文搜索)也是一种搜索,只不过它和数据库中使用 like 不同,全文检索使用了倒排索引的技术,它分为两步:

  • 索引创建:从数据中提取信息,建立倒排索引
  • 搜索索引:根据用户的查询去搜索索引,然后返回索引对应的结果

直接说的话不容易理解,我们举例说明,假设数据库中有一张表 game。

ElasticSearch 的概念解析与使用方式图片

假设要搜寻 type 字段包含 "校园" 或者 "爱情" 的记录,这个时候显然需要全表扫描。如果库里面有上千万条记录,那么就需要扫描上千万次,且每次扫描的范围都是全部的字符。此外这里指定了多个关键词,每个关键词都要模糊匹配一遍。

SELECT id, name FROM game
WHERE type LIKE '%校园%' OR type LIKE '%爱情%';

很明显这种 SQL 在 type 字段比较大的时候,其性能会非常差。

因此我们需要建立倒排索引,由于这里要基于 type 字段做查询,那么就对 type 字段的每一个文本进行拆分,得到多个关键词,然后再建立关键词到 id 的映射。

ElasticSearch 的概念解析与使用方式图片

通过对文本进行拆分,我们看到 type 字段包含 "亲情" 的有 id 为 1、2、3 的记录,包含 "夏日" 的有 id 为 2、3 的记录,所以每一个关键词都和包含该关键词的记录的 id 做了一个映射。

搜索的时候,同样也会对关键词、或者说要搜索内容进行拆分,得到更多的关键词,然后去匹配。假设我们想要根据 "校园爱情" 进行查找,那么会拆分成 "校园" 和 "爱情",然后直接就能得到 1、3、4、5,再根据 id 查找就可以了。

之前是逐行遍历去确定记录,现在是先根据关键词来确定 id,而构建的关键词到 id 的映射便是倒排索引。所以我们也可以发现,并不是说使用了 ES 之后就不需要数据库了。因为数据库表的字段可能非常多,我们不会对每一个字段都建立倒排索引,而是只针对那些需要通过关键词匹配的字段,将该字段的每一行都拆分成一个个的关键词,然后再把所有的关键词组合起来,建立它们到 id 之间的映射(倒排索引)。

因此在建立倒排索引后,行数反而会增多(如果大部分词都不一样的话),比如原来的数据有 100 万行,但是拆分出来的关键词有 200 万个,那么在建立倒排索引之后也会有 200 万行。但我们不可能真的搜索 200 万次,有可能我们搜索一次就找到对应的 id 了,因为在倒排索引中匹配的是关键词。

当然搜索一次是理想情况,也可能是十次、一百次,因此就需要设计一个好的搜索算法以及合适的数据组织结构来使得查询次数最小化,而算法如何设计显然不是我们需要操心的。并且在倒排索引中进行关键词匹配也和数据库的 like 不一样,前者只需要匹配单词即可,效率要比后者高很多。

以上便是全文检索以及倒排索引,还是很好理解的。然后再来说说 Lucene,其实 Lucene 就是一个 Jar 包,里面封装了很多建立倒排索引、以及搜索相关的算法。如果你使用 JAVA 语言的话,那么只需要引入这个 Jar 包,然后基于 Lucene 提供的 API 进行开发即可。通过 Lucene 我们就可以对已有的数据建立索引,Lucene 会在本地磁盘上面组织数据的索引结构。

 

什么是 ElasticSearch

 

 

了解了上面的内容之后,再来看 ES 就简单多了。我们说 Lucene 它封装了类似于搜索引擎的功能,但它是部署在单机上面的,如果数据量非常大、需要多机存储的话该怎么办呢。首先我们能想到的是把数据分散存储在多机上,然后每台机器各有一个 Lucene。

上面的做法看似解决了数据量的问题,但其实背后还有很多缺陷,比如:

  • 数据分散在多台机器上,这些数据要怎么切分?
  • 当我们在搜索的时候,如果数据存在多台机器上,那么是不是每台机器都需要访问呢?显然这会很麻烦。
  • 数据一旦分散在多台机器上,那么如何保证建立高性能的索引?
  • 数据的不丢失要如何保证,系统的高可用性要如何保证?

显然上述这几点都是问题,都要在考虑的范围内。因为任何框架,如果需要多机部署,那么之间就应该具备相互通信的功能,相互协调,彼此作为一个整体、像单机一样对外提供服务。

所以 ES 就应运而生,它是基于 Lucene 实现的一个搜索引擎,同样使用 Java 语言编写。但是通过 ES 可以让全文搜索变得更加简单,因为 Lucene 需要你有比较深的检索相关的知识,比较复杂,而 ES 将这种复杂隐藏了起来,让用户可以通过 RESTful API 进行查询。

不仅如此,ES 不仅仅是为了检索方便而封装的 Lucene,它还解决了分布式的问题。因为 Lucene 只是一个库,如果想支持多机部署,那么你需要额外做很多的工作。而 ES 把这些全部解决了,比如:

  • ES 具有分布式的文件存储,每个字段都可以被索引、被搜索
  • 自动维护数据在多个节点之间的分布,以及索引的建立、搜索请求的执行
  • 自动维护数据的冗余副本,一个节点宕掉了,不会造成数据的丢失
  • 可以轻松的扩展到上百台服务器,处理 PB 级结构化或非结构化数据
  • 除了 Lucene 的检索功能,ES 还封装了更多的高级功能,比如聚合分析、基于地理位置的搜索等等,可以让我们快速的开发应用,如果要基于原生的 Lucene 实现是很困难的

因此什么是 ES 我们就说完了,说白了 ES 就是一个基于 Lucene 实现的搜索引擎,并且支持高可用、可伸缩、分布式。每个节点之上都部署一个 ES,多个节点共同对外提供服务,至于节点之间如何协调 ES 内部已经帮我们做好了,无需我们关心。

此外,虽然我们一直说 ES 是一个搜索引擎,但其实 ES 不仅可以用来搜索,还可以用来做数据分析。比如电商网站通过 ES 选取 "百褶裙" 销量最高的十个商家,新闻网站通过 ES 选取访问量最高的几篇文章等等,显然此时在获取数据的同时也伴随着数据分析。因此 ES 是一个分布式的搜索和数据分析引擎,能够进行全文检索、结构化检索、数据分析,以及对海量数据进行接近实时的处理。

当然相信很多人都听过 ELK,是用来搭建日志分析平台的。其中 E 就是这里的 ElasticSearch,L 是 Logstash,K 是 Kibana。

  • Logstash 用来做数据采集;
  • ElasticSearch 负责数据分析;
  • Kibana 负责数据可视化;

我们后面也会涉及到 ELK。下面总结一下 ES 的特点:

  • 可以组成大型分布式集群,处理 PB 级数据,服务大公司;也可以运行在单机或者组成小型分布式集群,服务小公司。
  • ES 不是什么新技术,主要是将全文检索、数据分析以及分布式这些现有的技术合并在了一起,才形成了独一无二的 ES。
  • 对用户而言是开箱即用的,非常简单,作为中小型的应用,直接三分钟部署一下 ES 就可以作为生产环境的系统来用了。
  • 数据库的功能面对很多领域是不够用的,一些特殊的功能,像全文检索、同义词处理、相关度排名,复杂数据分析,海量数据的近实时处理等等,这些数据库是不支持的,而 ES 作为一个补充提供了数据库不具备的功能。

 

ElasticSearch 的核心概念

 

 

关于 ES,有几个专业术语,我们需要提前了解一下。

Cluster:集群,包含多个节点,当然也可以只包含一个节点。

Node:集群中的一个节点,每个节点都有一个名称(默认随机分配),节点的名称还是比较重要的,尤其是在执行运维管理操作的时候。

Index:索引,对应 MySQL 的数据库。

Type:类型,对应 MySQL 的表。

Document:文档,对应 MySQL 表中的一条记录,ES 的一个 Document 就类似于一条 JSON 数据。当然每条 JSON 数据可以有多个字段,然后字段在 ES 中被称为 Field,对应 MySQL 中的 Column。

shard:单台机器无法存储大量数据,ES 可以将一个索引中的数据切分为多个 shard,分布在多台服务器上存储。有了 shard 就可以横向扩展,存储更多的数据,让搜索和操作分布到多台服务器上去执行,提升吞吐性能。每个 shard 都是一个 Lucene Index,说白了就是 Index 的一个切片。

replica:任何一个服务器都有可能因为故障而宕机,造成 shard 丢失,因此可以为每一个 shard 创建多个 replica 副本。replica 可以在 shard 故障时提供备用服务,保证数据不丢失,此外多个 replica 还可以提升搜索操作的吞吐量和性能。

默认情况下,每个 Index 会被切分成 5 个 shard(建立索引时设置,设置后不能修改),被称为 primary shard。每个 primary shard 默认会有一个 replica shard(可以随时修改)。简单说的话,每个 Index 默认会被分成 5 个 shard,每个 shard 会有一个 replica。

当然啦,在 7.x 之前每个 Index 默认有 5 个 shard,但从 7.x 开始每个 Index 默认只有 1 个 shard。

因此在概念上,ES 和关系型数据库还是有一些共同之处的。

ElasticSearch 的概念解析与使用方式图片

需要注意的是,随着 ES 的发展,Type 的概念逐渐在弱化,因为全文索引的目的是建立关键词到 id 的映射,所以 Type 和全文索引的概念是冲突的。在 ES 6.x 中,已经规定一个 Index 下只能包含一个 Type,而到 ES 7.x 时,Type 的概念就被完全移除了。

 

安装 ElasticSearch

 

 

下面来安装 ES,这里我使用的是云服务器,操作系统是 centos 7。由于 ES 是基于 Java 语言编写的,所以理论上在安装 ES 之前要先安装 JDK,但 ES 从 8.x 开始已经自带 JDK 了,因此我们就不需要再单独安装了。

然后去 ES 官网下载相应的安装包,这里我下载的是最新版 8.11.3,然后上传到服务器,并解压到 /opt 目录中。当然,如果你的节点上安装了 Docker,那么也可以基于容器启动。

ElasticSearch 的概念解析与使用方式图片

安装成功,然后看一下 ES 的主目录,是不是很熟悉呢。所有 Java 编写的大数据组件都是类似的,每个目录作用如下:

  • bin 目录放一些启动脚本、以及用于命令行操作的脚本;
  • config 目录放一些配置文件;
  • lib 目录存放程序依赖的 jar 包;
  • logs 目录负责存放日志文件;
  • modules 目录存放功能模块;
  • plugins 目录存放一些插件。

然后里面还有一个 jdk 目录,也就是 Java 环境,所以即使当前的系统没有安装,也是没关系的。

下面我们启动 ES,不过启动之前需要修改一下配置文件 config/elasticsearch.yml。

# ES 默认只允许本机访问,将其修改为 0.0.0.0
network.host: 0.0.0.0
# 端口默认为 9200
http.port: 9200

然后再创建用户,因为 ES 要求不能以 root 用户启动,因此我们要创建一个用户,并赋予它相关权限。

# 创建一个组 es
groupadd es
# 创建一个用户 es,并关联到组 es 中
useradd es -g es
# 赋予它 ES 目录的操作权限
chown es:es /opt/elasticsearch-8.11.3/ -R

下面切换用户,进入 ES 目录中,输入 bin/elasticsearch 启动 ES。如果你配置了环境变量,那么直接输入 elasticsearch 就行。

但如果你启动时发现报了下面这个错,那么说明空间不足。

ElasticSearch 的概念解析与使用方式图片

此时应该修改 config/jvm.options 配置文件。

# 设置 JVM 的初始内存为 1G,此值可以与 -Xmx 相同
# 避免每次垃圾回收完成后 JVM 重新分配内存
-Xms1g
# 设置 JVM 最大可用内存为 1G
-Xmx1g

然后再来启动 ES,默认是以前台启动的。但如果你发现输出一堆日志信息后,进程又退出了,并且最后输出了 ERROR: Elasticsearch exited unexpectedly, with exit code 78。那么你需要切换回 root 用户,然后执行如下命令:

sysctl -w vm.max_map_count=262144

然后再打开 /etc/security/limits.conf,并在里面追加如下内容。

es hard nofile 65536
es soft nofile 65536

这里的 es 就是刚才创建的用户,如果你创建的用户不叫 es,那么记得修改。

完事之后,再切换回 es 用户,再次启动,会发现启动成功。然后我们测试一下,浏览器中输入 http://ip:9200 ,看看能否返回内容。

然而很不幸,会发现无法访问,并且 ES 会输出如下内容:

ElasticSearch 的概念解析与使用方式图片

这是因为 ES 默认只允许通过 HTTPS 访问,如果想支持 HTTP,那么需要再次修改配置文件。

打开 config/elasticsearch.yml,在里面配置如下内容:

# 是否需要用户名密码,这里改成 false
xpack.security.enabled: false
# 是否开启 SSL 认证,这里将 enabled 给改成 false
# 否则只允许 https 请求,而 http 请求会被拒绝
xpack.security.http.ssl:
  enabled: true
  keystore.path: certs/http.p12

然后重新启动 ES,此时再访问 ip:9200 就没有问题了,会返回如下内容。

ElasticSearch 的概念解析与使用方式图片

返回了一条 JSON,我们说 ES 的 Document(文档)就类似于一条 JSON,其字段就是 Field。然后里面的 name 字段表示节点名称,cluster_name 表示集群名称,这些都可以通过配置文件 elasticsearch.yml 进行修改,至于其它字段就见名知意了。

到目前为止,整个 ES 算是启动成功了,但目前是前台启动,我们需要改成后台启动。

bin/elasticsearch -d

只需要在结尾加一个 -d 即可。

 

小结

到目前为止,我们就介绍了什么是 ES,以及它解决了什么问题。然后了解了它的核心概念,以及安装方式。



Tags:ElasticSearch   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Elasticsearch 性能优化详解
硬件配置优化升级硬件设备配置一直都是提高服务能力最快速有效的手段,在系统层面能够影响应用性能的一般包括三个因素:CPU、内存和 IO,可以从这三方面进行 ES 的性能优化工作。...【详细内容】
2024-03-07  Search: ElasticSearch  点击:(25)  评论:(0)  加入收藏
ElasticSearch 的概念解析与使用方式
ElasticSearch(后续简称 ES)在企业中的使用可以说是非常广泛了,那么 ES 到底是什么呢?我们学习 ES 能做到哪些事情呢?接下来我将用几篇文章详细聊一聊 ES。ES 是一款高性能的分布...【详细内容】
2023-12-29  Search: ElasticSearch  点击:(111)  评论:(0)  加入收藏
一口气看完43个关于 ElasticSearch 的实操建议
一、前言本文分享了在工作中关于 ElasticSearch 的一些使用建议。和其他更偏向手册化更注重结论的文章不同,本文将一定程度上阐述部分建议背后的原理及使用姿势参考,避免流于...【详细内容】
2023-12-28  Search: ElasticSearch  点击:(94)  评论:(0)  加入收藏
一口气看完 43 个关于 ElasticSearch 的使用建议
一、前言本文分享了在工作中关于 ElasticSearch 的一些使用建议。和其他更偏向手册化更注重结论的文章不同,本文将一定程度上阐述部分建议背后的原理及使用姿势参考,避免流于...【详细内容】
2023-12-19  Search: ElasticSearch  点击:(174)  评论:(0)  加入收藏
Elasticsearch与文件描述符的恩恩怨怨
提到Elasticsearch,让笔者最恶心的倒不是它的反人类的DSL设计,而是每次安装都需要修改进程的最大文件描述符。那ES与文件描述符有啥恩怨呢,下面就来唠叨唠叨。首先说说文件描述...【详细内容】
2023-12-13  Search: ElasticSearch  点击:(121)  评论:(0)  加入收藏
Mongodb和Elasticsearch计算经纬度哪个性能更好
MongoDB和Elasticsearch都支持计算经纬度距离,但它们的性能表现可能因使用场景和数据规模而异。性能对比1、数据索引和存储 MongoDB使用地理空间索引(2dsphere)来支持经纬度数...【详细内容】
2023-12-11  Search: ElasticSearch  点击:(205)  评论:(0)  加入收藏
SpringBoot整合ElasticSearch详解及相关使用方法
环境:springboot2.4.12 + ElasticSearch7.8.0简介Elasticsearch是一个分布式搜索引擎,底层基于Lucene实现。它屏蔽了Lucene的底层细节,提供了分布式特性,同时对外提供了Restful...【详细内容】
2023-11-10  Search: ElasticSearch  点击:(201)  评论:(0)  加入收藏
Elasticsearch的实际应用与扩展案例
当谈到搜索和分析大量数据时,Elasticsearch 是一个强大且广泛使用的工具。它是一个开源的分布式搜索和分析引擎,被设计用于处理海量数据,并提供实时的搜索、分析和可视化功能。...【详细内容】
2023-10-16  Search: ElasticSearch  点击:(269)  评论:(0)  加入收藏
十分钟掌握Doris,超越Hive、Elasticsearch和PostgreSQL
以前,数据仓库通常由Apache Hive、MySQL、Elasticsearch和PostgreSQL组成。它们支持数据仓库的数据计算和数据存储层: 数据计算:Apache Hive作为计算引擎。 数据存储:MySQL为Dat...【详细内容】
2023-09-27  Search: ElasticSearch  点击:(223)  评论:(0)  加入收藏
何时使用Elasticsearch,而不是MySQL?
MySQL 和 Elasticsearch 是两种不同的数据管理系统,它们各有优劣,适用于不同的场景。本文将从以下几个方面对它们进行比较和分析: 数据模型 查询语言 索引和搜索 分布式和高可...【详细内容】
2023-08-22  Search: ElasticSearch  点击:(195)  评论:(0)  加入收藏
▌简易百科推荐
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(5)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(12)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(8)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(10)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(8)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
Kubernetes 究竟有没有 LTS?
从一个有趣的问题引出很多人都在关注的 Kubernetes LTS 的问题。有趣的问题2019 年,一个名为 apiserver LoopbackClient Server cert expired after 1 year[1] 的 issue 中提...【详细内容】
2024-03-15  云原生散修  微信公众号  Tags:Kubernetes   点击:(5)  评论:(0)  加入收藏
站内最新
站内热门
站内头条