索引
MySQL B+ tree
能够帮助用户进行范围查询,精确查询。把一个字段的前几个字节,拿出来匹配。但其没办法做全文索引,因为key/value 不能把全文中的任意一个字段,都做成索引
倒排索引
根据关键字找文档,支持用户任何关键字搜素内容,一般我们面对两种场景
- 面向客户端(百度 google)
- 面向服务端(存储日志,搜素日志,当日志有上百亿条时)
搜索引擎
luence
luence是java语言研发的,是个类库,他将用户要搜索的内容,构建成要搜索的格式。本身不能执行,必须在此基础上开发外壳
在Luence上开发的软件:solr(搜索引擎)
在搜索之前,我们要把数据传到一个特有的文件系统上去,我们要对存储系统的每行文本信息进行切词,切词完成后要做格式转换。使之大小不同但单词相同,或者同义词....能被搜索到
{ClientIP:ip,ident:ID,user:USER,timestamp:time}
当我们要检索10.0.0.1,这个IP时,clientIP,是要搜索内容的标识符,及解释这个字段是干什么的
上述的每一行,就称为一个文档。我们对文档进行访问,然后对每个词加上个描述信息。同一类型多个文档组合一起,称为type(myql中的表),多个type组成起来称为索引(mysql中的库)。
对于任何一个数据拿过来,我们都要做抽取,转换,装入。
转换:把数据进行切词,转换
装入:我们把每个数据项,做成一个文档。每一个文档,就是对应现实中独立的数据项,每一个网页就是一个文档。比如一个word,就是一个文档,一个网页,也是一个文档
多个文档(document)组织在一起,就是Type
Type相当于关系型数据库中的表
Document ----> ROW
Type ----> Table
Index ----> Database
搜索本身,就是从index上,底下的type和document里面的一个字段值(搜索本身是在本地数据库进行的)
lucence不能直接接收用户请求,也不能检索数据
只能在luence上加个外壳,用于接收用户请求,存入数据,把数据转换成document,存放在数据库中。用户检索数据时,外壳将数据转换成luence的格式,进行检索,在接收luence响应返回给用户
sphinx
C++
用户存取数据
首先把数据存到shard中,shard中通过中心节点,把数据存到哪台服务器上,做的是二级路由
shard默认5分,可以手动指定。
节点数量大于等于shard数量
对数据的保障性,做冗余,对节点做主从或把shard当成主从
要求副本不能和主分片不能在同一台机器上,副本数量代表同时最多坏掉的节点的数量
一般我们做一主两副
每一个分片在每一个节点上都是一个单独的索引,副本数量越多,空间利用率越低
新版本的elasticsearch 只支持单播通信
logstash 日志抓取工具,jruby 跑在java虚拟机上的ruby
filebeat收集日志的
kibana 支持以elasticsearch 为数据源的展示接口
分布式文件系统中,时间一定要同步
elasticsearch集群搭建
# 三个机器network,不一样和主机名不一样
[root@db02 ~]# grep -v "#" /etc/elasticsearch/elasticsearch.yml
cluster.name: my-test
node.name: node-1
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 10.0.0.12
http.port: 9200
discovery.zen.ping.unicast.hosts: ["10.0.0.12", "10.0.0.15","10.0.0.13"] //使用zen方式进行选主,使用单播通信
discovery.zen.minimum_master_nodes: 2 //最少有几个主节点,集群为可用状态
9300: 为elasticsearch内部通信判断谁是leader
9200:面向客户端通信
logstash
rpm -ivh logstash-6.6.0.rpm
echo "PATH=$PATH:/usr/share/logstash/bin/" >> /etc/profile
[root@ceshi conf.d]# cat logstash.conf
input {
stdin {} 标准输入
}
output {
stdout {} 标准输出
}
--------------------------------------------------------------------------------
[root@ceshi conf.d]# cat logstash-code.conf
input {
stdin {}
}
output {
stdout {
codec => rubydebug //codec编码器,把标准输入转换为什么格式
}
}
----------------------------------------------------------------------------------------------------------------
[root@ceshi conf.d]# cat logstash-file.conf
input {
file {
path => ["/var/log/httpd/access_log"] //logstash 从文件中获取内容,path文件的路径
start_position => "beginning" // begining 代表从头开始进行收集,end代表从上次结束时进行收集
}
}
output {
stdout {
codec => rubydebug
}
}
日志中的内容,全部放在message里面了,要对message里面的字段进行使用json字段进行
-----------------------------------------------------------------------------------------------------------
[root@ceshi conf.d]# cat logstash-file-grok.conf
input {
file {
path => ["/var/log/httpd/access_log"]
start_position => "beginning"
}
}
filter {
grok {
match => {"message" => "%{HTTPD_COMBINEDLOG}"} //把message字段中的内容转换成json格式,rpm -ql logstash |grep patter,中的httpd 文件,打开
remove_field => "message" 移除message字段
}
}
output {
stdout {
codec => rubydebug
}
}
-------------------------------------------------------------------------------------------------------------------------
[root@ceshi conf.d]# cat logstash-file-grok-date.conf
input {
file {
path => ["/var/log/httpd/access_log"]
start_position => "beginning"
}
}
filter {
grok {
match => {"message" => "%{HTTPD_COMBINEDLOG}"}
remove_field => ["message","timestamp"]
}
date {
match => ["timestamp","dd/MMMM/YYYY:H:m:s","Z"] //此处的时区,恰好与本地时区差8个小时
}
}
output {
stdout {
codec => rubydebug
}
}
----------------------------------------------------------------------------------------------------------------------
输出到elasticsearch中
[root@ceshi conf.d]# cat logstash-file-grok-date-elasticsearch.conf
input {
file {
path => ["/var/log/httpd/access_log"]
start_position => "beginning"
}
}
filter {
grok {
match => {"message" => "%{HTTPD_COMBINEDLOG}"}
remove_field => ["message","timestamp"]
}
date {
match => ["timestamp","dd/MMMM/YYYY:H:m:s","Z"]
}
}
output {
elasticsearch {
hosts => ["http://10.0.0.12:9200","http://10.0.0.15:9200","http://10.0.0.13:9200"]
index => "logstash-%{+YYYY.MM.dd}" //索引的名字
document_type => "apache_logs" //文档的类型
}
}
filebeat
cat filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/httpd/access_log
output.logstash:
hosts: ["10.0.0.15:5044"]
-----------------------------------------------------------------------------------
为了区分不同的日志信息,给filebeat收集的日志增加字段
[root@ceshi filebeat]# egrep -v "#|^$" filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/httpd/access_log
fields:
log_type: access
- type: log
paths:
- /var/log/httpd/error_log
fields:
log_type: errors
output.logstash:
hosts: ["10.0.0.15:5044"]
logstash
[root@ceshi conf.d]# cat logstash-file-grok-date-elasticsearch.conf
input {
beats {
port => 5044
}
}
filter {
if [fields][log_type] == "access" {
grok {
match => {"message" => "%{HTTPD_COMBINEDLOG}"}
remove_field => ["message","timestamp"]
}
date {
match => ["timestamp","dd/MMMM/YYYY:H:m:s","Z"]
}
} else if [fields][log_type] == "errors" {
grok {
match => {"message" => "%{HTTPD_ERRORLOG}"}
}
}
}
output {
if [fields][log_type] == "access"{
elasticsearch {
hosts => ["http://10.0.0.12:9200","http://10.0.0.15:9200","http://10.0.0.13:9200"]
index => "access-%{+YYYY.MM.dd}"
document_type => "apache_access_logs"
}
} else if [fields][log_type] == "errors" {
elasticsearch {
hosts => ["http://10.0.0.12:9200","http://10.0.0.15:9200","http://10.0.0.13:9200"]
index => "error-%{+YYYY.MM.dd}"
document_type => "apache_error_logs"
}
}
}
使用redis 中间件
filebeat
[root@ceshi filebeat]# egrep -v "#|^$" filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/httpd/access_log
fields:
log_type: access
- type: log
paths:
- /var/log/httpd/error_log
fields:
log_type: errors
output.redis:
enabled: true
hosts: ["10.0.0.15:6379"]
port: 6379
key: filebea
datatype: list
password: czazm
db: 0
logstash
[root@ceshi conf.d]# cat logstash-file-grok-date-elasticsearch-redis.conf
input {
redis {
host => "10.0.0.15"
port => 6379
key => "filebeat"
db => 0
data_type => list
password => czazm
}
}
filter {
if [fields][log_type] == "access" {
grok {
match => {"message" => "%{HTTPD_COMBINEDLOG}"}
remove_field => ["message","timestamp"]
}
date {
match => ["timestamp","dd/MMMM/YYYY:H:m:s","Z"]
}
} else if [fields][log_type] == "errors" {
grok {
match => {"message" => "%{HTTPD_ERRORLOG}"}
}
}
}
output {
if [fields][log_type] == "access"{
elasticsearch {
hosts => ["http://10.0.0.12:9200","http://10.0.0.15:9200","http://10.0.0.13:9200"]
index => "access-%{+YYYY.MM.dd}"
document_type => "apache_access_logs"
}
} else if [fields][log_type] == "errors" {
elasticsearch {
hosts => ["http://10.0.0.12:9200","http://10.0.0.15:9200","http://10.0.0.13:9200"]
index => "error-%{+YYYY.MM.dd}"
document_type => "apache_error_logs"
}
}
}
网友评论