【转载保存】索引文件锁LockFactory

索引文件锁LockFactory

  LockFactory在Lucene中用来对索引文件所在的目录进行加锁,使得同一时间总是只有一个IndexWriter对象可以更改索引文件,即保证单进程内(single in-process)多个不同IndexWriter对象互斥更改(多线程持有相同引用的IndexWriter对象视为一个IndexWriter不会受制于LockFactory,而是受制于对象锁(synchronized(this))、多进程内(multi-processes)多个对象互斥更改。

LockFactory的具体实现类

  LockFactory是一个抽象类,提供了以下几种子类,即NoLockFactory、SingleInstanceLockFactory、SimpleFSLockFactory、NativeFSLockFactory、VerifyingLockFactory,下面一一介绍。

图1:

NoLockFactory

  该类的功能同类名一样,即不会对索引文件进行加锁,如果使用者有把握(certain)使得IndexWriter对象总是能互斥更改索引文件,那么可以不对索引文件所在的目录进行加锁。

SingleInstanceLockFactory

  该类是RAMDirectory默认使用的索引文件锁,RAMDirectory属于Directory类的子类,Directory类描述了索引文件所在目录的一些信息,以后会有文章介绍Directory类。

  对于拥有相同RAMDirectory对象的多个IndexWriter对象,实现不同IndexWriter之间对索引文件的互斥更改。

获得索引文件锁

  该过程十分的简单,故给出完整的代码:

 

 

  final HashSet<String> locks = new HashSet<>();
  // 尝试获得索引文件锁,如果已经占用则抛出异常
  public Lock obtainLock(Directory dir, String lockName) throws IOException {
    synchronized (locks) {
      if (locks.add(lockName)) {
        return new SingleInstanceLock(lockName);
      } else {
        throw new LockObtainFailedException("lock instance already obtained: (dir=" + dir + ", lockName=" + lockName + ")");
      }
    }
  }

  在IndexWriter类中,定义了一个不可更改的lockName,使得无论哪个线程通过IndexWriter来获得索引文件锁时,lockName的值都是相同的,这样就能通过判断该lockName是否在locks容器中来实现互斥,lockName在IndexWriter类中的定义如下:

图2:

释放索引文件锁

  释放锁的过程即从locks容器(HashSet对象)中移除键值为write.lock的元素。

FSLockFactory

  FSLockFactory是一个抽象类,它有两个子类分别是SimpleFSLockFactory,NativeFSLockFactory,用来专门指定给FSDirectory类提供索引文件锁(can only be used with FSDirectory subclasses)。

SimpleFSLockFactory

  该类只能用于FSDirectory,FSDirectory跟RAMDirectory一样是Directory的子类。

  该类通过在索引文件所在目录创建一个名为write.lock文件的方式来实现索引文件锁,该方法的缺点在于如果JVM异常退出,那么索引文件锁可能无法被释放,即没有删除write.lock文件。

  解决的方法只能是通过手动删除write.lock文件,注意是,手动删除前用户得自己保证(certain)目前没有IndexWriter正在写入,否则非常容易破坏(corrupt)索引文件,比如说由于删除了write.lock文件,使得多个IndexWriter对象同时更改了索引文件。

获得索引文件锁

  在索引文件所在目录生成一个write.lock文件,并且记录该文件的创建时间,目的是在任意阶段可以检查该文件是否被外在力量(external force)篡改了,从而判定该锁的合法性(valid),在该类中,如果发现被篡改,那么就抛出异常。

  比如每次添加一篇文档(Document)后,将该Document的信息写入索引文件之前会做检查(调用该类的ensureValid( )方法),如果此时发现write.lock被篡改了(比如说被删除了),那么这次写入就会失败,后续的处理会在以后介绍IndexWriter时详细介绍。

释放索引文件锁

  释放锁的过程即删除write.lock文件,如果发现write.lock文件的创建时间跟获得该锁的时间不同,那么就抛出异常来让用户决定如何处理这种情况,使用Files.delete(Path path)的方法来尝试删除write.lock文件,如果出错了,那么同样地抛出异常让用户决定如何处理这种情况。

NativeFSLockFactory

  NativeFSLockFactory同SimpleFSLockFactory一样,只能用于FSDirectory,它是Directory默认使用的LockFactory的,同样的通过在索引文件所在目录生成一个write.lock文件,但是该类还使用了FileChannel来管理write.lock文件。

获得索引文件锁

  NativeFSLockFactory获得索引文件锁的过程分为两步:

  • 第一步:判断write.lock文件是否已经被进程内(in-process)的其他线程的不同IndexWriter对象占有,通过一个线程安全的同步Set容器(Collection.synchronizedSet())实现,最先到的(first come)的线程会将write.lock文件的绝对路径写入到同步Set容器中,后来的线程尝试添加路径时会抛出异常
  • 第二步:使用FileChannel来尝试获得进程间(inter-process)级别的文件锁FileLock,即判断write.lock文件是否被其他进程占用,如果占用则直接抛出异常。

  另外也会记录write.lock文件的创建时间,用法跟SimpleFSLockFactory一样。

  同SimpleFSLockFactory一样,在运行过程中,当更改索引文件时(添加文档、更新、commit、flush等变更索引文件的操作),依次判断下面的条件,任意一个条件不满足时说明当前索引文件锁是不合法的:

  • 条件1:进程内的某个线程调用了close(),如果该线程继续执行更改索引操作,会抛出异常
  • 条件2:如果同步Set容器不包含write.lock文件的绝对路径,会抛出异常
  • 条件3:FileChannel的锁FileLock是不合法的状态,这种情况是未知的外部力量(external force)导致的, 会抛出异常
  • 条件4:FileChannel中的channel的值不是0,Lucene不会对write.lock文件写入任何数据,所以如果发现该文件中被添加了数据则抛出异常
  • 条件5:当前write.lock文件的创建时间跟获得锁时的创建时间不一致,说明被未知的(external force)修改了,会抛出异常

释放索引文件锁

  该类释放锁的过程分两步走:

  • 释放write.lock文件的FileLock
  • 清空同步Set容器中的内容

SimpleFSLockFactory与NativeFSLockFactory各自的特点

  尽管NativeFSLockFactory是默认的FSDirectory的索引文件锁,但基于实际场景,有时候使用SimpleFSLockFactory能更好的工作(work perfectly)。

  • NativeFSLockFactory基于 java.nio.*来获得FileLock,但在某些文件系统下可能会受限,比如说在NFS下可能无法获得FileLock(the lock can incorrectly be double acquired),此时使用SimpleFSLockFactory就不会有这个问题
  • 当JVM异常退出时,残留的(leftover)write.lock文件无法删除,如果使用SimpleFSLockFactory需要手动的去删除该文件,否则尝试获得索引文件锁时就直接抛出异常,而使用NativeFSLockFactory时,不用关心当前write.lock文件是否被正确删除,因为它只关心write.lock是否被其他进程占用,而JVM异常退出后,会自动释放FileLock(操作系统会释放FileLock),所以不能通过判断write.lock文件在索引文件的目录中就认为索引文件被锁定了(locked),Lucene从不会因为异常去删除write.lock文件

VerifyingLockFactory

  该类不同于上面提到的NoLockFactory、SingleInstanceLockFactory、SimpleFSLockFactory、NativeFSLockFactory,如果上述这些索引文件锁在实际业务还是无法正确的工作(not working properly),那么可以使用VerifyingLockFactory封装上述的LockFactory,通过一个开启一个LockVerifyServer(单独的服务)来实现认证(verify),保证不会发生同一时间两个进程同时获得锁的情况。

认证方法

  Lucene7.5.0中通过Socket向LockVerifyServer发送特定的字节来尝试获得锁,同样的通过发送特定字节来释放锁,由于源码中的实现过于简单,一般不会直接使用,故不详细介绍。

结语

  本文介绍了实现互斥访问索引文件的索引文件锁LockFactory。

转载:https://www.codercto.com/a/84611.html

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IndexOptions类说明

IndexOptions是在lucene-core-x.jar包下面&#xff0c;其作用是在新建索引时候选择索引属性。 IndexOptions是一个枚举类&#xff1a; 枚举变量说明&#xff1a; NONE不被索引DOCS_AND_FREQS文档和词频建立索引DOCS_AND_FREQS仅对文档和词频建立索引DOCS_AND_FREQS_AND_POSIT…

【转载保存】lucene正则查询使用注意

今天要分享的是关于lucene中另外一种丰富的查询方式----正则查询&#xff0c;lucene内置了许多的查询API&#xff0c;以及更强大的自定义查询方式的QueryParse&#xff0c;大部分情况下我们使用内置的查询API&#xff0c;基本上就可以满足我们的需求了&#xff0c;但是如果你想…

【转载保存】搜索引擎调研文档

搜索引擎选型调研文档 Elasticsearch简介* Elasticsearch是一个实时的分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据。 它可以用于全文搜索&#xff0c;结构化搜索以及分析&#xff0c;当然你也可以将这三者进行组合。 Elasticsearch是一个建立在全…

lucene详细说明文档

以下部门功能在lucene5以上版本可能有的API所有改变 目录1.简介 2.了解索引操作 2.1倒排索引 2.2字段类型 2.3细分 2.4文件编号 2.5搜索索引 3.创建索引 4.基本索引操作 4.1核心索引类 4.2将数据添加到索引 5.文件和领域 5.1文件 5.2领域 5.3在Lucene中增强文档 1.简介 该索引是…

分布式集群架构场景解决方案学习笔记

课程学习 一致性哈希算法集群时钟同步问题分布式ID解决方案分布式任务调度问题session共享(一致性)问题 一致性哈希算法 一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的&#xff0c;设计目标是为了解决因特网中的热点(Hot spot)问题&#xff0c…

分布式学习-总结

文章目录分布式理论分布式系统定义以及面临的问题分布式系统定义分布式面临的问题通信异常网络分区三态节点故障分布式理论&#xff1a;一致性概念分布式一致性的提出强一致性弱一致性最终一致性分布式事务CAP定理什么是CAP理论&#xff1f;为什么只能3选2能不能解决3选2的问题…

什么叫死锁?死锁案例?死锁必须满足哪些条件?如何定位死锁问题?有哪些解决死锁策略?哲学家问题?

1.死锁是什么&#xff1f; 死锁一定发生在并发环境中&#xff0c;死锁是一种状态&#xff0c;当两个(或者多个线程)相互持有对方所需要的资源&#xff0c;却又都不主动释放手中持有的资源&#xff0c;导致大家都获取不到自己想要的资源&#xff0c;所有相关的线程无法继续执行…

dubbo启动服务启动报错.UnsatisfiedDependencyException: Error creating bean with name '***': Un

报错信息&#xff1a; 今天部署开发环境的时候这个问题弄了一下午&#xff0c;由于我本地启动是好的&#xff0c;然后部署到服务器老是启动不了&#xff0c;报如上错&#xff0c;后来经过排查发现是provider.xml和consumer.xml中的如下代码version属性版本信息不一致。 <du…

【转载保存】dubbo学习笔记

Dubbo Dubbo简介 首先&#xff0c;我理解的Dubbo&#xff0c;从大的方向来看是单体应用到分布式应用过度期的一个产物&#xff0c;具体来说应该是分布式应用从早期的SOA到微服务过度的一个产物。 在编写分布式场景下高并发、高扩展的系统对技能的要求很高&#xff0c;因为这…

mysql搭建手册

mysql搭建手册 主从搭建 搭建mysql 关闭防火墙&#xff1a;systemctl stop firewalld 如果失败先安装 yum install iptables-services 配置数据库 /etc/my.cnf&#xff0c;配置同步数据库等 主库配置信息 [mysqld] datadir/usr/local/mysql/data log-error/usr/local/mysql/…

MongoDb安装配置

Mongodb学习 Mongodb安装 1.下载社区版 MongoDB 4.1.3 去官网下载对应的MongoDB 然后上传到Linux虚拟机 2.将压缩包解压即可 tar -zxvf MongoDB-linux-x86_64-4.1.3.tgz3.启动 mkdir -p /data/db./bin/mongod4.指定配置文件方式的启动 配置文件样例: dbpath/data/mongo…

FastDFS学习笔记

FastDFS课程内容 第一部分&#xff1a;FastDFS基础回顾 为什么要有分布式文件系统、分布式文件系统对比、FastDFS特性、linux安装、java访问FastDFS 第二部分&#xff1a;FastDFS系统架构和功能原理 架构详解、架构设计的概念、设计理念、功能原理(上传、下载、文件同步、删…

redis主从搭建和分片集群搭建

文章目录redis主从搭建搭建一主一从&#xff1a;下载安装redis&#xff1a;两台机器都需要操作权限认证理解主从复制原理、同步数据集全量同步三个阶段&#xff1a;增量同步&#xff1a;心跳检测redis哨兵模式部署方案搭建配置哨兵模式原理建立连接获取主服务器信息获取从服务器…

如何利用redis实现秒杀系统

文章目录题记利用Watch实现Redis乐观锁题记 在线思维导图总结&#xff1a;redis大纲 利用Watch实现Redis乐观锁 乐观锁基于CAS&#xff08;Compare And Swap&#xff09;思想&#xff08;比较并替换&#xff09;&#xff0c;是不具有互斥性&#xff0c;不会产生锁等待而消 耗…

教你如何使用redis分布式锁

文章目录一、redis客户端实现应用1.利用set nx命令实现分布式锁2.利用分布式锁命令 setnx问题1.为什么不直接调用jedis.del(key)方法而采用redislua实现&#xff1f;2.上述两种方式存在的问题&#xff1f;3.根本原因分析二、分布式场景Redission分布式锁的使用1.分布式锁的特性…

本地缓存之Guava简单使用

文章目录使用场景Guava Cache 的优势Guava Cache使用CacheLoaderCallable删除主动删除过期删除基于容量删除引用删除高级用法并发设置更新锁定GuavaCache高级实战之疑难问题GuavaCache会oom&#xff08;内存溢出&#xff09;吗GuavaCache缓存到期就会立即清除吗GuavaCache如何找…

java中强引用、弱引用、软引用、虚引用学习

文章目录强引用弱引用软引用虚引用将引用之前首先让我们一起回顾一下java对象的生命周期强引用 在实际开发场景中&#xff0c;我们一般使用的都是强引用&#xff0c;只要强引用存在&#xff0c;垃圾回收即使OOM也不会回收&#xff0c;知道强引用释放以后&#xff0c;对象才会被…

mysql left join、right join、inner join、union、union all使用以及图解

左外连接&#xff1a;left join sql语法&#xff1a;LEFT JOIN LEFT OUTER JOIN 首先需要创建两张表做测试&#xff0c;表数据如下所示 table 1 表&#xff1a; table2 表&#xff1a; 查询sql&#xff1a; select * from table1 a LEFT JOIN table2 b on a.idb.id 总结&a…

第十八章 Swing程序设计

Swing用于开发桌面窗体程序&#xff0c;是JDK的第二代GUI框架&#xff0c;其功能比JDK第一代GUI框架AWT更为强大、性能更加优良。但因为Swing技术推出时间太早&#xff0c;其性能、开发效率等不及一些其他流行技术&#xff0c;所以目前市场上大多数桌面窗体程序都不是由Java开发…

redis stream学习总结

文章目录streamStream基本概念消息id消息内容增删查改消息生产添加消息 xadd查看消息长度 xlen限制stream最大长度1.xadd 中添加**maxlen**:2.xtrim查询消息 xrange正向排序&#xff1a;消费id从小到大排反向查询&#xff1a;消费id从大到小排删除消息消息消费独立消费 xread消…