lucene indexwriter锁机制

最近有个项目要用solr,solr是基于lucene的,今天在测试indexwriter时遇到了lock的问题:

测试代码:

import java.io.File;
import java.io.IOException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
public class TestLock {
    private Directory dir;
    public static TestLock ttt;
    public static IndexWriter writer2;
    private Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_48);
    private IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_48, analyzer);
    public void init() throws Exception {
        String pathFile = "D://luceneindex";
        try{
               dir = FSDirectory. open(new File(pathFile));
        } catch (IOException e) {        
            throw new RuntimeException(e);
        }
        IndexWriter writer = getWriter();             
        System. out.println("init ok,test IndexWriter lock" );
        LockTest( writer);      
        //writer.close();
    }
    public IndexWriter getWriter() throws Exception {
        //analyzer.close();
        return new IndexWriter(dir, iwc);
    }
    public void LockTest(IndexWriter w1) {
       try{
               if(w1.isLocked (dir )){
                     System. out.println("write1 locked" );
                     IndexWriterConfig iwc1 = new IndexWriterConfig(Version.LUCENE_48 , analyzer );
                      writer2 = new IndexWriter(dir, iwc1); 
              } else{
                     System. out.println("write1 not locked" );                      
              }      
       } catch(Exception e){
              e.printStackTrace();
       }       
    }  
    public static void main(String[] args){
       ttt = new TestLock();
       try{
               ttt.init();
       } catch(Exception e){
              e. printStackTrace();              
       }      
    }
}

报错信息:

org.apache.lucene.store.LockObtainFailedException : Lock obtain timed out: [email protected]:\luceneindex\write.lock: java.nio.channels.OverlappingFileLockException
       at org.apache.lucene.store.Lock.obtain( Lock.java:89)
       at org.apache.lucene.index.IndexWriter.<init>( IndexWriter.java:710)
       at TestLock.LockTest( TestLock.java:38)
       at TestLock.init( TestLock.java:26)
       at TestLock.main( TestLock.java:51)
Caused by: java.nio.channels.OverlappingFileLockException
       at sun.nio.ch.SharedFileLockTable.checkList(Unknown Source)
       at sun.nio.ch.SharedFileLockTable.add(Unknown Source)
       at sun.nio.ch.FileChannelImpl.tryLock(Unknown Source)
       at java.nio.channels.FileChannel.tryLock(Unknown Source)
       at org.apache.lucene.store.NativeFSLock.obtain(NativeFSLockFactory.java:148)
       at org.apache.lucene.store.Lock.obtain( Lock.java:100)
       ... 4 more

从错误信息可以看到是IndexWriter获取锁出错导致,从堆栈信息可以看到,是在运行IndexWriter的构造方法时,涉及到锁的操作。

查看IndexWriter的相关源码:

doc:
Opening an IndexWriter creates a lock file for the directory in use. Trying to open another IndexWriter  on the same directory will lead to a
LockObtainFailedException. The  LockObtainFailedException is also thrown if an IndexReader on the same directory is used to delete documents
from the index.

两个和锁相关的属性:

  public static final String WRITE_LOCK_NAME = "write.lock" ;
  private Lock writeLock;

在IndexWriter的构造函数中:

  public IndexWriter(Directory d, IndexWriterConfig conf) throws IOException
....
     directory = d;
.....
    writeLock = directory.makeLock(WRITE_LOCK_NAME);
    if (! writeLock.obtain(config .getWriteLockTimeout())) // obtain write lock(尝试获取锁)
      throw new LockObtainFailedException("Index locked for write: " + writeLock );

其中Lock是一个抽象类(org.apache.lucene.store.Lock):

锁的获取主要实现是在obtain方法:

  public static long LOCK_POLL_INTERVAL = 1000;
  public static final long LOCK_OBTAIN_WAIT_FOREVER = -1;
  public final boolean obtain(long lockWaitTimeout) throws IOException {
    failureReason = null;
    boolean locked = obtain();
    if (lockWaitTimeout < 0 && lockWaitTimeout != LOCK_OBTAIN_WAIT_FOREVER )
      throw new IllegalArgumentException("lockWaitTimeout should be LOCK_OBTAIN_WAIT_FOREVER or a non-negative number (got " + lockWaitTimeout + ")");
    long maxSleepCount = lockWaitTimeout / LOCK_POLL_INTERVAL;
    long sleepCount = 0;
    while (!locked) {
      if (lockWaitTimeout != LOCK_OBTAIN_WAIT_FOREVER && sleepCount++ >= maxSleepCount) {
        String reason = "Lock obtain timed out: " + this .toString();
        if (failureReason != null) {
          reason += ": " + failureReason ;
        }
        LockObtainFailedException e = new LockObtainFailedException(reason);
        if (failureReason != null) {
          e.initCause( failureReason);
        }
        throw e;
      }
      try {
        Thread. sleep(LOCK_POLL_INTERVAL);
      } catch (InterruptedException ie) {
        throw new ThreadInterruptedException(ie);
      }
      locked = obtain();
    }
    return locked;
  }

可以看到有由下面几个因素决定:

1.lockWaitTimeout 超时时间(总时间,超过这个时间即timeout),默认1000ms

2.LOCK_OBTAIN_WAIT_FOREVER  是否无限获取(-1),如果设置为-1,会永不超生

3.LOCK_POLL_INTERVAL  重试间隔时间,默认1000ms

在关闭IndexWriter时调用close方法(实现了Closeable接口的类都会有close方法)即可正常释放锁

更改代码为如下即可:

  public void LockTest(IndexWriter w1) {
       try{
               if(w1.isLocked (dir )){
                     System. out.println("write1 locked" );
                     w1.close();
                     IndexWriterConfig iwc1 = new IndexWriterConfig(Version.LUCENE_48 , analyzer );
                      writer2 = new IndexWriter(dir, iwc1); 
              } else{
                     System. out.println("write1 not locked" );                      
              }      
       } catch(Exception e){
              e.printStackTrace();
       }       
    }

另外关于lock的判断和unlock方法如下:

 public static boolean isLocked(Directory directory) throws IOException {  // 判断写目录是否被lock
    return directory.makeLock( WRITE_LOCK_NAME).isLocked();
  }
  /**
   * Forcibly unlocks the index in the named directory.
   * <P>
   * Caution: this should only be used by failure recovery code,
   * when it is known that no other process nor thread is in fact
   * currently accessing this index.
   */
  public static void unlock(Directory directory) throws IOException { // 解锁
    directory.makeLock(IndexWriter. WRITE_LOCK_NAME).close();
  }

lucene indexwriter锁机制

时间: 2024-10-08 02:23:07

lucene indexwriter锁机制的相关文章

JAVA synchronized关键字锁机制(中)

synchronized 锁机制简单的用法,高效的执行效率使成为解决线程安全的首选. 下面总结其特性以及使用技巧,加深对其理解. 特性: 1. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.       2. 当一个线程同时访问object的一个synchronized(this)同步代码块时,其它线程仍然可以访问非修饰的方法或代码块.       3. 当多个线程同时访问object的synchronized(this)同步代码

Java并发编程:Concurrent锁机制解析

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

Mysql事务,并发问题,锁机制-- 幻读、不可重复读(转)

1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约束没有被破坏 持久性:事务的提交结果,将持久保存在数据库中 2.事务并发会产生什么问题 1)第一类丢失更新:在没有事务隔离的情况下,两个事务都同时更新一行数据,但是第二个事务却中途失败退出, 导致对数据的两个修改都失效了. 例如: 张三的工资为5000,事务A中获取工资为5000,事务B获取工资为5

【转】数据库锁机制

1 前言 数据库大并发操作要考虑死锁和锁的性能问题.看到网上大多语焉不详(尤其更新锁),所以这里做个简明解释,为下面描述方便,这里用T1代表一个数据库执行请求,T2代表另一个请求,也可以理解为T1为一个线程,T2 为另一个线程.T3,T4以此类推.下面以SQL Server(2005)为例. 2 锁的种类 共享锁(Shared lock). 例1: ---------------------------------------- T1: select * from table (请想象它需要执行

Mysql中那些锁机制之InnoDB

我们知道mysql在曾经.存储引擎默认是MyISAM.可是随着对事务和并发的要求越来越高,便引入了InnoDB引擎.它具有支持事务安全等一系列特性. InnoDB锁模式 InnoDB实现了两种类型的行锁. 共享锁(S):同意一个事务去读一行,阻止其它事务获得同样的数据集的排他锁. 排他锁(X):同意获得排他锁的事务更新数据,可是组织其它事务获得同样数据集的共享锁和排他锁. 能够这么理解: 共享锁就是我读的时候,你能够读,可是不能写.排他锁就是我写的时候.你不能读也不能写.事实上就是MyISAM的

并发编程(四):也谈谈数据库的锁机制

http://www.2cto.com/database/201403/286730.html 1. 数据库并发的问题 数据库带来的并发问题包括: 1. 丢失更新. 2. 未确认的相关性(脏读). 3. 不一致的分析(非重复读). 4. 幻像读. 详细描述如下: 1.1.丢失更新 当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题.每个事务都不知道其它事务的存在.最后的更新将重写由其它事务所做的更新,这将导致数据丢失. e.g.事务A和事务B同时修改某行的值, 事务A

[数据库事务与锁]详解四: 数据库的锁机制

注明: 本文转载自http://www.hollischuang.com/archives/898 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数据库都提供了锁机制,并引入了事务隔离级别的概念. 并发控制 在计算机科学,特别是程序设计.操作系统.多处理机和数据库等领域,并发控制(Concurrency control)是确保及时纠正由并发操作导致的错误的一种机制. 数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存

利用锁机制解决商品表和库存表并发问题

锁机制 问题:当一个脚本被一个客户端访问都正常,但当多个客户端同时并发访问时,这个脚本的结果会出现不正确,这个问题需要使用锁机制来解决.在我们这个网站中需要用到锁的地方就是高并发下定单时减少商品库存量时. 比如例子1: 有一个A 表里面一个ID数字: 现在写一个脚本操作这个A表,每次访问把ID减少: 这个脚使用AB模拟10个用户并发访问时会发现减少的数量并不是10: . 例子2:在高并发下定单时如果要减少库存量,那么库存就会出问题: 加锁之前: 加锁之后: 现在有两种锁机制:MYSQL中的表锁和

深入浅出 Java Concurrency (9): 锁机制 part 4[转]

本小节介绍锁释放Lock.unlock(). Release/TryRelease unlock操作实际上就调用了AQS的release操作,释放持有的锁. public final boolean release(int arg) {    if (tryRelease(arg)) {        Node h = head;        if (h != null && h.waitStatus != 0)            unparkSuccessor(h);