redis主从之全量复制及增量复制

主从注意事项

对于主从复制的好处,在上篇文章我也写了,下面说一下注意事项。

注意事项

  • 安全

    对于数据比较重要的节点,主节点会通过设置requirepass参数进行密码验证,这时候所有的客户端访问必须使用auth命令进行验证。从节点与主节点的复制链接是通过一个特殊标识的客户端来完成。因此需要配置从节点的masterauth参数与主节点密码保持一致,这样从节点才可以正确地链接到主节点并发起复制流程。

  • 从节点只读

    默认情况下slave-read-only=yes配置为只读,由于复制只能从主节点到从节点,对于从节点的任何修改主节点都无法感知,修改从节点会造成主从数据不一致。因此没必要就不要动这个配置。

  • 网络延迟问题

    主从节点一般部署在不同机器上,复制时的网络延迟就成为需要考虑的问题,redis为我们提供了repl-disable-tcp-nodelay参数用于控制是否关闭 tcp nodelay,默认是关闭的,说明如下:

    关闭时,主节点产生的命令数据无论大小都会及时地发送给从节点,这样主从之间延迟将会变小,但增加了网络宽带的消耗。适用于主从之间的网络环境较好的场景。

    开启时,主节点会合并较小的TCP数据包从而节省宽带。默认发送时间间隔取决于Linux的内核,一般默认为40ms。这种配置节省了宽带但增大主从之间的延迟。适用于主从网络环境复杂或宽带紧张的场景。

部署主从节点时需要考虑网络延迟、宽带使用率、防灾级别等因素,如要求低延迟时,建议同机房部署并关闭repl-disable-tcp-nodelay,如考虑容灾性,可以跨机房部署并开启repl-disable-tcp-nodelay

拓扑图

一主一从

1
2
3
4
5

graph TD

A[Redis-master] --> B[Redis-slave]

一主多从

1
2
3
4
5
graph TD

A[Redis-master] --> B[Redis-slave]
A[Redis-master] --> C[Redis-slave]
A[Redis-master] --> D[Redis-slave]

树状主从

1
2
3
4
5
6
graph TD

A[Redis-master] --> B[Redis-slave]
A[Redis-master] --> C[Redis-slave]
B[Redis-slave] --> D[Redis-slave]
B[Redis-slave] --> E[Redis-slave]

原理

1
2
3
4
5
6
7
8
9
10
graph TD

A[slaveof] -->|127.0.0.1:6379| B[slave]
B[slave] --> D[保存主节点信息]
D[保存主节点信息] --> E[主从建立socket连接]
E[主从建立socket连接] --> F[发送ping命令]
F[发送ping命令] --> G[权限验证]
G[权限验证] --> H[同步数据集]
H[同步数据集] --> I[命令持续复制]
I[命令持续复制] --> J[master]

从上图可以看出来大致分为6个过程:

  • 执行slaveof后从节点保存主节点的地址信息便返回,这时候复制流程还没开始。
  • 从节点内部通过每秒运行的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后,会尝试与该节点建立网络连接,从节点会建立一个socket套接字。
  • 发送ping命令,检测主从之间网络套接字是否可用,检测主节点是否可用接受处理命令。如果发送 ping 命令后,从节点没有收到主节点的 pong 回复或者超时,比如网络超时或者主节点正在阻塞无法响应命令,从节点会断开复制连接,下次定时任务会发起重连。
  • 如果主节点配置了requirepass参数,则需要密码认证,从节点必须配置masterauth参数保证与主节点相同的密码才能通过验证。
  • 主从复制连接正常通信后,对于首次建立复制的场景,主节点会把持有的数据全部发送给从节点,这部分操作是耗时最长的步骤。
  • 当主节点把当前的数据同步给从节点后,便完成了复制的建立流程。接下来主节点会持续地把写命令发送给从节点,保证主从数据一致性。

主从同步的过程中,从节点会把原来的数据清空。

数据同步

同步方式:

  • 全量复制

    用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点。当数据量过大的时候,会造成很大的网络开销。

  • 部分复制

    用于处理在主从复制中因网络闪退等原因造成数据丢失场景,当从节点再次连上主节点,如果条件允许,主节点会补发丢失数据给从节点,因为补发的数据远远小于全量数据,可以有效避免全量复制的过高开销。但需要注意,如果网络中断时间过长,造成主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制 。

复制偏移量:

  • 参与复制的主从节点都会维护自身复制偏移量,主节点在处理完写入命令操作后,会把命令的字节长度做累加记录,统计信息在info replication中的master_repl_offset指标中。

  • 从节点每秒钟上报自身的复制偏移量给主节点,因此主节点也会保存从节点的复制偏移量slave0:ip=192.168.1.3,port=6379,state=online,offset=116424,lag=0

  • 从节点在接收到主节点发送的命令后,也会累加记录自身的偏移量。统计信息在info replication中的slave_repl_offset中。

复制积压缓冲区:

  • 复制积压缓冲区是保存在主节点上的一个固定长度的队列,默认大小为1MB,当主节点有连接的从节点时被创建,这时主节点响应写命令时,不但会把命令发给从节点,还会写入复制积压缓冲区。
  • 在命令传播阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积压缓冲区,作为写命令的备份;除了存储写命令,复制积压缓冲区中还存储了其中 的每个字节对应的复制偏移量(offset) 。由于复制积压缓冲区定长且先进先出,所以它保存的是主节点最近执行的写命令;时间较早的写命令会被挤出缓冲区。

主节点运行ID:

  • 每个redis节点启动后都会动态分配一个40位的十六进制字符串为运行ID。运行ID的主要作用是来唯一识别redis节点,比如从节点保存主节点的运行ID识别自已正在复制是哪个主节点。如果只使用ip+port的方式识别主节点,那么主节点重启变更了整体数据集(如替换RDB/AOF文件),从节点再基于偏移量复制数据将是不安全的,因此当运行ID变化后从节点将做全量复制。可以在info server命令查看当前节点的运行ID。
  • 需要注意的是redis关闭再启动,运行的id会随之变化。

Psync命令:

  • 从节点使用psync命令完成部分复制和全量复制功能psync runid offset
  • 流程说明:
    • 从节点(slave)发送psync命令给主节点,参数runid是当前从节点保存的主节点运行id,如果没有则默认值为 ?, 参数offset是当前从节点保存的复制偏移量,如果是第一次参与复制则默认值为-1。
    • 主节点根据pysnc参数和自身数据情况决定响应结果:
      • 如果回复+FULLRESYNC {runid} {offset},那么从节点将触发全量复制流程。
      • 如果回复+CONTINUE,从节点将触发部分复制流程。
      • 如果回复-ERR,说明主节点版本低于Redis2.8。

全量复制流程:

  • 发送psync命令进行数据同步,由于是第一次进行复制,从节点没有复制偏移量和主节点的运行id,所以发送psync ? -1
  • 主节点根据psync ? -1解析出当前为全量复制,回复+FULLRESYNC响应(主机会向从机发送 runid 和 offset,因为 slave 并没有对应的 offset,所以是全量复制)
  • 从节点接收主节点的响应数据保存运行ID和偏移量offset(从机 slave 会保存 主机master 的基本信息 save masterInfo)
  • 主节点收到全量复制的命令后,执行bgsave(异步执行),在后台生成RDB文件(快照),并使用一个缓冲区(称为复制缓冲区)记录从现在开始执行的所有写命令
  • 主节点发送RDB文件给从节点,从节点把接收到的RDB文件保存在本地并直接作为从节点的数据文件,接收完RDB后从节点打印相关日志,可以在日志中查看主节点发送的数据量(主机send RDB 发送 RDB 文件给从机)
    • 注意!对于数据量较大的主节点,比如生成的RDB文件超过6GB以上时要格外小心。传输文件这一步操作非常耗时,速度取决于主从节点之间网络带宽。
    • 通过细致分析Full resync和MASTER <-> SLAVE这两行日志的时间差,可以算出RDB文件从创建到传输完毕消耗的总时间。如果总时间超过repl-timeout所配置的值 (默认60秒),从节点将放弃接受RDB文件并清理已经下载的临时文件,导致全量复制失败;针对数据量较大的节点,建议调大repl-timeout参数防止出现全量同步数据超时;
    • 例如对于千兆网卡的机器,网卡带宽理论峰值大约每秒传输100MB,在不考虑其他进程消耗带宽的情况下,6GB的RDB文件至少需要60秒传输时间,默认配置下,极易出现主从数同步超时。
  • 对于从节点开始接收RDB快照到接收完成期间,主节点仍然响应读写命令,因此主节点会把这期间写命令数据保存在复制客户端缓冲区内,当从节点加载完RDB文件后,主节点再把缓冲区内的数据发送给从节点,保证主从之间数据致性。(发送缓冲区数据)
  • 从节点接收完主节点传送来的全部数据后会清空自身旧数据(刷新旧的数据,从节点在载入主节点的数据之前要先将老数据清除)
  • 从节点清空数据后开始加载RDB文件,对于较大的RDB文件,这一步操作依然比较消耗时间,可以通过计算日志之间的实际差来判断加载RDB的总消耗时间(加载 RDB 文件将数据库状态更新至主节点执行bgsave时的数据库状态和缓冲区数据的加载。)
  • 从节点成功加载完RDB后,如果当前节点开启了AOF持久化的功能,它会立刻做bgrewriteeaof的操作,为了保证全量复制后AOF持久化文件立刻可用。 通过分析全量复制的所有流程,全量复制是一个非常耗时费力的操作。他的实际开销主要包括:
    • 主节点bgsave时间
    • RDB文件网络传输时间
    • 从节点清空数据时间
    • 从节点加载RDB的时间
    • 可能的AOF重写时间

部分复制流程:

  • 部分复制是 Redis 2.8 以后出现的,之所以要加入部分复制,是因为全量复制会产生很多问题,比如像上面的时间开销大、无法隔离等问题, Redis 希望能够在主节点出现抖动(相当于断开连接)的时候,可以有一些机制将复制的损失降低到最低

  • 当主从节点之间网络出现中断时,如果超过repl-timeout时间,主节点会认为从节点出问题了并断开复制链接(如果网络抖动(连接断开 connection lost))。

  • 主从连接中断期间主节点依然响应命令,但因复制链接中断命令无法发送给从节点不过主节点内部存在的复制积压缓存去,依然可以保存一段时间的写命令数据,默认最大缓存1MB(主机master 还是会写 replbackbuffer(复制缓冲区))

  • 当主从节点网络恢复后,从节点会再次连上主节点。(从机slave会继续尝试连接主机)

  • 当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行id。因此会把他们当作psync参数发送给主节点,要求进行部分复制操作。(从机 slave 会把自己当前 runid 和偏移量传输给主机 master,并且执行 pysnc 命令同步)

  • 主节点接到psync命令后首先核对参数的runid,如果 master 发现你的偏移量是在缓冲区的范围内,根据参数offset在缓冲区查找复制内内,如果在偏移量之后的数据存在缓存区中,则对从节点发送continue表示可以进行部分复制

  • 主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。(同步了 offset 的部分数据,所以部分复制的基础就是偏移量 offset)

心跳:

主节点在建立成功后会维护这长连接彼此发送心跳检测

  • 主从节点彼此都有心跳检测机制,各自模拟成对方的客户端进行通信,通过client list命令查看复制相关客户端信息,主节点的连接状态为flags=M,从节点连接状态 flags=S。
  • 主节点默认每隔10秒对从节点发送ping命令,判断从节点的存活性和连接状态。可通过参数repl-ping-slave-period控制发送频率。
  • 从节点在主线程中每隔1秒发送replconf ack {offset} 命令,给主节点上报自身当前的复制偏移量。

缓冲区大小调节:

  • 由于缓冲区长度固定且有限,因此可以备份的写命令也有限,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。
  • 反过来说,为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小(通过配置repl-backlog-size)来设置;
  • 例如 如果网络中断的平均时间是 60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见, 可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。

微服务架构常见的分布式事务解决方案

场景问题

多个服务,位于不同主机,不同的网络当中,没有办法用本地事务保证要么一起成功,要么一起失败。

BASE理论

BA: Basic Availability 基本业务可用性(支持分区失败)

S: Soft state 柔性状态(状态允许有短时间不同步,异步)

E: Eventual consistency 最终一致性(最终数据是一致的,但不是实时一致)

原子性(A)与持久性(D)必须根本保障

为了可用性、性能与降级服务的需要,只有降低一致性( C ) 与 隔离性( I ) 的要求

酸碱平衡(ACID-BASE Balance)

CAP定理

对于共享数据系统,最多只能同时拥有CAP其中的两个,没法三者兼顾。

任意两者的组合都有其适用场景

真实系统应当是ACID与BASE的混合体

不同类型的业务可以也应当区别对待

CAP定理

解决方案

可靠消息最终一致性(异步确保型)

实现

业务处理服务在业务事务提交前,向实时消息服务请求发送消息,实时消息服务只记录消息数据,而不真正发送。业务处理服务在业务事务提交后,向实时消息服务确认发送。只有在得到确认发送指令后,实时消息服务才真正发送

消息

业务处理服务在业务事务回滚后,向实时消息服务取消发送。消息状态确认系统定期找到未确认发送或回滚发送的消息,向业务处理服务询问消息状态,业务处理服务根据消息ID或消息内容确定该消息是否有效

约束

被动方的处理结果不影响主动方的处理结果,被动方的消息处理操作是幂等操作

成本

可靠消息系统建设成本

一次消息发送需要两次请求,业务处理服务需实现消息状态回查接口

优点、适用范围

消息数据独立存储、独立伸缩,降低业务系统与消息系统间的耦合

方案特点

兼容所有实现AMQP标准的MQ中间件

确保业务数据可靠的前提下,实现业务数据的最终一致(理想状态下基本是准实时一致)

柔性事务解决方案 TCC(两阶段型、补偿型)

实现

一个完整的业务活动由一个主业务服务与若干从业务服务组成

主业务服务负责发起并完成整个业务活动

从业务服务提供TCC型业务操作

业务活动管理器控制业务活动的一致性,它登记业务活动中的操作,并在业务活动提交时确认所有的TCC型操作的confirm操作,在业务活动取消时调用所有TCC型操作的cancel操作

成本

实现TCC操作的成本

业务活动结束时confirm或cancel操作的执行成本

业务活动日志成本

适用范围

强隔离性、严格一致性要求的业务活动

适用于执行时间较短的业务(比如处理账户、收费等业务)

用到的服务模式

TCC操作、幂等操作、可补偿操作、可查询操作

方案特点

不与具体的服务框架耦合(在RPC架构中通用)

位于业务服务层,而非资源层

可以灵活选择业务资源的锁定粒度

最大努力通知型

实现

业务活动的主动方,在完成业务处理之后,向业务活动的被动方发送消息,允许消息丢失。

业务活动的被动方根据定时策略,向业务活动主动方查询,恢复丢失的业务消息。

约束

被动方的处理结果不影响主动方的处理结果

成本

业务查询与校对系统的建设成本

使用范围

对业务最终一致性的时间敏感度低

跨企业的业务活动

方案特点

业务活动的主动方在完成业务处理后,向业务活动被动方发送通知消息(允许消息丢失)主动方可以设置时间阶梯型通知规则,在通知失败后按规则重复通知,直到通知N次后不主动方提供校对查询接口给被动方按需校对查询,用于恢复丢失的业务消息

应用案例

银行通知、商户通知等(各大交易业务平台间的商户通知:多次通知、查询校对、对账文件)


ElasticSearch全文检索引擎-使用

ElasticSearch使用

手册官网

es-docs
es-php-docs

索引

  1. 创建索引

    vim createindex.json

     {
         "settings": {
             "refresh_interval": "5s",
             "number_of_shards": 1,
             "number_of_replicas": 0
         },
         "mappings": {
             "_default_": {
                 "_all": {
                     "enabled": true
                 }
             }
         },
         "products": {
             "dynamic": false,
             "properties": {
                 "productid": {
                     "type": "long"
                 },
                 "title": {
                     "type": "string",
                     "index": "analyzed",
                     "analyzer": "ik"
                 },
                 "descr": {
                     "type": "string",
                     "index": "analyzed",
                     "analyzer": "ik"
                 }
             }
         }
     }
    

    具体的字段意思手册上都有

    创建

    curl -XPOST "http://ip:port/shop" -d'@createindex.json

    这里的shop就是我们要设置的索引名称 可以自定义
    products 是 索引的type类型 可以自定义

  2. 添加数据

    curl -XPUT "http://119.23.51.33:9200/shop/products/1" -d'{"productid":1,"title":"这是一个商品的标题","descr":"这是一个商品的描述"}'

`curl -XPUT "http://ip:port/shop/products/2?pretty" -d'{"productid":2,"title":"这是一部手机","descr":"这是一个苹果手机的描述信息"}'`

url地址后面的整值要跟文章id一致

pretty就是 Elasticsearch美化输出(pretty-print)JSON响应以便更加容易阅读。
  1. 搜索数据

    vim search.json

      {
         "query": {
             "multi_match": {
                 "query": "苹果",
                 "fields": [
                     "title",
                     "descr"
                 ]
             }
         },
         "highlight": {
             "pre_tags": [
                 "<em>"
             ],
             "post_tags": [
                 "</em>"
             ],
             "fields": {
                 "title": {},
                 "descr": {}
             }
         }
     }
     
    

    query 要查询的关键字
    fields 哪些字段需要被查询
    highlight 被查询出来的关键字 进行一些改变 相当于高亮显示
    pre_tags 标签开始 post_tags标签结束

    测试

    curl -XGET "http://ip:port/shop/_search?pretty" -d"@search.json"

elasticsearch-jdbc

将数据库的数据同步到elasticsearch

  1. 下载

    wget http://xbib.org/repository/org/xbib/elasticsearch/importer/elasticsearch-jdbc/2.3.4.0/elasticsearch-jdbc-2.3.4.0-dist.zip

    unzip elasticsearch-jdbc-2.3.4.0-dist.zip

  1. 修改配置

    cd elasticsearch-jdbc-2.3.4.0/bin

    为了防止出错 先备份一下

    cp mysql-blog.sh mysql-blog.sh.bak

    vim mysql-blog.sh

    将 echo 下的内容替换成以下内容

     {
         "type" : "jdbc",
         "jdbc" : {
             "url" : "jdbc:mysql://localhost:3306/good",
             "user" : "root",
             "password" : "1C292567e208",
             "sql" : "select productid,title,descr,productid as _id from test",
             "index" : "shop",
             "type" : "products",
             "elasticsearch" : {
                  "cluster" : "search",
                  "host" : "ip",
                  "port" : 9300
             }   
         }
     }
    

    url 是我们的数据库 good是库名 对哪个库进行操作
    user password 用户名和密码
    sql语句 就是 执行后 把查询出来的数据添加到es中
    这里呢productid as _id 是因为es的唯一标识是根据_id生成的
    index 我们刚刚创建的索引名称
    products 是索引type类型
    cluster 是我们es配置文件中的项目名称
    host port 分别为ip和端口号 port为9300 这个地方不可以改

  2. 运行

    ./mysql-blog.sh

    curl -XGET "http://119.23.51.33:9200/shop/_search?pretty"

    可以看到数据库的内容被添加进去了

    但是修改数据库内容 或者 添加内容 es却不会改变 下面怎么改变呢

  3. 监控 实时同步

     {
         "type" : "jdbc",
         "jdbc" : {
             "url" : "jdbc:mysql://localhost:3306/good",
             "schedule" : "0 0-59 0-23 ? * *",
             "user" : "root",
             "password" : "1C292567e208",
             "sql" : [{
                     "statement": "select productid,title,descr,productid as _id from test where updatetime > unix_timestamp(?) ",
                     "parameter": ["$metrics.lastexecutionstart"]}
                 ],
             "index" : "shop",
             "type" : "products",
             "metrics": {
                 "enabled" : true
             },
             "elasticsearch" : {
                  "cluster" : "search",
                  "host" : "ip",
                  "port" : 9300
             }   
         }
     }
     
    

    这时需要一个字段去判断 那就是我们数据的修改时间
    parameter 里面的内容 就是获取上次脚本执行时间
    sql 的where条件 就是判断 修改时间大于上次脚本执行时间 就属于新数据

    重新执行下脚本 就可以了

    怎么用php操作呢

    现在有好多框架的轮子

    或者直接看es-php-docs

    php框架:

    laravel-elasticsearch
    yii2-elasticsearch
    去GitHub上查找就行

ElasticSearch全文检索引擎-安装

ElasticSearch安装

安装JDK

  1. 下载rpm包

    wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "https://download.oracle.com/otn-pub/java/jdk/8u201-b09/42970487e3af4f5aa5bca3f542482c60/jdk-8u201-linux-x64.rpm"

  2. rpm安装

    rpm -ivh jdk-8u201-linux-x64.rpm
    安装成功后测试 java javac java -version 命令都能使用

安装ElasticSearch

  1. 官网
    ElasticSearch

  2. 下载
    这里我下载的2.4.6版本

    wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/rpm/elasticsearch/2.4.6/elasticsearch-2.4.6.rpm

  3. 安装ElasticSearch

    yum install elasticsearch-2.4.6.rpm

  4. 修改配置文件

    vim /etc/elasticsearch/elasticsearch.yml

    cluster.name: my-application这行取消注释 并且改为自己的应用名称
    node.name: node-1 这行也一样 改为自己的节点名称
    为了方便操作 应用名称改为 search 节点名称为 master
    network.host: 192.168.0.1 取消注释 改为 0.0.0.0
    http.port: 9200 取消注释就行 可以自行修改端口号
    切记 取消注释后 首字母前面不能有空格 不然启动会报错

  5. 运行ElasticSearch

    service elasticsearch start
    浏览器访问ip+端口号 如果出现界面证明 成功

安装ik中文分词

  1. ik分词地址

    ik

  2. 安装git和maven

    如果有的话跳过此步

    安装git
    yum install -y git

    下载maven包
    wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz

    解压到指定目录
    tar -xzvf apache-maven-3.5.4-bin.tar.gz -C /usr/local

    进入指定目录
    cd /usr/local/

    创建软连接
    ln -s apache-maven-3.5.4 maven

    编辑文件 添加maven环境变量
    vim /etc/profile

    在文件末尾添加以下代码
    MAVEN_HOME=//usr/local/maven
    export MAVEN_HOME
    export PATH=${PATH}:${MAVEN_HOME}/bin

    运行命令
    source /etc/profile

    mvn -v
    出现版本 安装maven成功

  3. 安装ik分词
    克隆
    git clone https://github.com/medcl/elasticsearch-analysis-ik.git

    根据elasticsearch版本号切换相对应的ik分词版本号 这里es是2.4.6 相对应是1.10.6

    克隆好之后进入该目录
    cd elasticsearch-analysis-ik/

    切换版本
    git checkout tags/v1.10.6

    执行
    mvn package

    执行成功后会在 target/releases/ 目录下生成一个插件包 进入该目录
    cd target/releases/

    复制到es的插件目录下解压
    cp elasticsearch-analysis-ik-1.10.6.zip /usr/share/elasticsearch/plugins/

    进入目录
    cd /usr/share/elasticsearch/plugins/

    解压
    unzip elasticsearch-analysis-ik-1.10.6.zip

    为了方便管理 新建个文件夹 把刚刚解压出来的文件移动进去
    mkdir ik
    mv ./* ik

    重启elasticsearch
    service elasticsearch restart

    测试下
    curl -XPOST "http://ip:port/_analyze?analyzer=ik&pretty" -d '这是一个商品的标题'


ElasticSearch和ik分词安装成功

ElasticSearch全文检索引擎-介绍

全文检索

种将文件种或者数据库中所有文本与检索项匹配的文字资料检索方法。对全文数据的检索

数据分类:

  • 结构化数据

      行数据,存储在数据库里,可以用二维表结构来逻辑表达实现的数据 
      能够用数据或统一的结构加以表示 
      数字、符号去表示
    
  • 非结构化数据

      无法用数字或统一的结构表示
      文本、图像、声音、网页
      结构化数据属于非结构化数据
      非结构化数据即为全文数据
    
两种方法
  • 顺序扫描法

      将数据库中所有的内容挨个扫描
    
  • 索引扫描法

      全文检索的基本思路,也即将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
    
全文检索过程
  • 索引创建
      索引保存的是一个词元,对应文档的id
      索引只会创建一次
    

如何创建:

  1.     一些要索引的原文档(Document)
    
  2.     将原文档传给分词组件(Tokenizer)
    
  3.     将得到的词元(Token)传给语言处理组件(LinguisticProcessor)
    
  4.  将得到的词(Term)传给索引组件(Indexer)
    
         
    
  • 搜索索引
  1.     用户输入查询语句
    
  2.     对查询语句进行词法分析,语法分析,及语言处理
    
  3.     搜索索引,得到符号文档
    

全文检索引擎

全文检索引擎是目前广泛应用的主流搜索引擎。
它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。

相关产品

Lucene,Sphinx,Xapian,Nutch,DataparkSearch…

ElasticSearch

ElasticSearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的,功能最全的搜索引擎库。

为什么要选择ElasticSearch

ElasticSearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

分布式的实时文件存储,每个字段都被索引可被搜索
分布式的实时分析搜索引擎
可以扩展到上百台服务器,处理PB级结构化或非结构化数据

所有功能都集成在一个服务里面,可以通过RESTful API、各种语言的客户端甚至命令行与之交互
上手容易,提供了很多合理的缺省值,开箱即用,学习成本低
可免费下载、使用和修改 配置灵活