.net lucene lucene.net

Concurrencia en Lucene.NET.



(3)

En primer lugar tenemos que definir una operación de "escritura". Una operación de escritura objetará un bloqueo una vez que comience una operación de escritura y continuará hasta que cierre el objeto que está realizando el trabajo. Por ejemplo, al crear un IndexWriter e indexar un documento, la escritura se opondrá a un bloqueo y mantendrá este bloqueo hasta que cierre el IndexWriter.

Ahora podemos hablar un poco de la cerradura. Este bloqueo que es objeto es un bloqueo basado en archivos. Al igual que mythz mencionado anteriormente, hay un archivo llamado ''write.lock'' que se crea. Una vez que se opone un bloqueo de escritura es exclusivo! Este bloqueo hace que todas las operaciones de modificación de índice (IndexWriter y algunos métodos de IndexReader) esperen hasta que se elimine el bloqueo.

En general usted y tiene múltiples lecturas en un índice. Incluso puedes leer y escribir al mismo tiempo, no hay problema. Pero hay un problema al tener varios escritores. Si un hilo está esperando el bloqueo demasiado tiempo, se desactivará.

1) Posible Solución # 1 Operaciones Directas

Si está seguro de que sus operaciones de indexación son cortas y rápidas, es posible que pueda usar el mismo índice al mismo tiempo. De lo contrario, tendrá que pensar en cómo desea organizar las operaciones de indexación de las aplicaciones.

2) Posible solución # 2 Servicio web

Dado que está trabajando con una solución web, es posible crear un servicio web. Al implementar este servicio web, dedicaría un hilo de trabajo para la indexación. Yo crearía una cola de trabajo para contener el trabajo y si la cola contenía varios trabajos para realizar, debería tomarlos todos y hacerlos en lotes. Esto solucionará todos los problemas.

3) crear otro índice, luego fusionar

Si la aplicación de la consola realiza un trabajo pesado en el índice, puede considerar que la aplicación de la consola pueda crear un índice separado en la aplicación de la consola y luego fusionar los índices en un tiempo programado seguro utilizando IndexWriter.AddIndexes.

desde aquí puede hacer esto de dos maneras, puede fusionarse con el índice directo. O puede fusionar para crear un tercer índice, y luego, cuando este índice esté listo, reemplace el índice original. También debe tener cuidado con lo que está haciendo aquí para asegurarse de que no va a bloquear algo de uso intensivo y provocar un tiempo de espera para otras operaciones de escritura.

4) Índice y búsqueda de índices múltiples

Personalmente creo que la gente necesita separar sus índices. Esto ayuda a separar las responsabilidades de los programas y minimiza el tiempo de inactividad y mantiene un solo punto para todos los índices. Por ejemplo, si su aplicación de consola es responsable de agregar solo ciertos campos o si está extendiendo un índice, puede ver los índices separados, pero mantener la identidad utilizando un campo de ID en cada documento. Ahora, con esto, puede aprovechar el soporte incorporado para buscar múltiples índices utilizando la clase MultiSercher. O si desea, también hay una buena clase ParallelMultiSearch que puede buscar ambos índices a la vez.

5) Mira en SOLR

Otra cosa que puede ayudar a su problema de mantener un solo lugar para su índice, podría cambiar su programa para que funcione con un servidor SOLR. http://lucene.apache.org/solr/ también hay una bonita biblioteca de SOLRNET http://code.google.com/p/solrnet/ que puede ser útil en esta situación. Aunque no tengo experiencia con solr, tengo la impresión de que te ayudará a manejar situaciones como esta. También tiene otros beneficios, como el resaltado de resultados y la búsqueda de elementos relacionados al encontrar elementos "Más como este", o proporcionar corrección ortográfica.

Estoy seguro de que hay otros métodos, pero estos son todos los que puedo pensar. En general, su solución depende de la cantidad de personas que escriben y de la actualización del índice de búsqueda que necesita. En general, si puede aplazar algunas operaciones por un momento y realizar algunas operaciones por lotes en cualquier situación, obtendrá el mayor rendimiento. Mi sugerencia es que entiendas con qué puedes trabajar e ir desde allí. buena suerte

Quiero usar Lucene.NET para la búsqueda de texto completo compartida entre dos aplicaciones: una es una aplicación MVC de ASP.NET y la otra es una aplicación de consola. Se supone que ambas aplicaciones deben buscar y actualizar el índice. ¿Cómo se debe manejar la concurrencia?
Encontré un tutorial en ifdefined.com donde se discute el caso de uso similar. Mi preocupación es que el bloqueo será un gran cuello de botella.

PD: También noté que IndexSearcher usa una instantánea del índice y en el tutorial mencionado anteriormente, el buscador se crea solo cuando se actualiza el índice. ¿Es este un buen enfoque? ¿Puedo crear un objeto de búsqueda regular en cada búsqueda y, en caso afirmativo, cuál es la sobrecarga?

Encontré una pregunta relacionada. Lo que afirma que la concurrencia entre procesos es seguro. ¿Significa que no hay condiciones de carrera para el índice?

También un aspecto muy importante. ¿Cuál es el impacto del rendimiento involucrado si digamos que 10-15 hilos están intentando actualizar el índice de Lucene mediante la adquisición de un bloqueo compartido presentado en esta solución ?

Después de usarlo durante un par de meses, tengo que agregar que el índice de apertura para la búsqueda a menudo puede crear una excepción OutOfMemory bajo altas cargas de CPU y memoria si la consulta utiliza la clasificación. El costo de la operación de apertura del índice es pequeño (según mi experiencia) pero el costo de GC puede ser bastante alto.


También tengo un índice de búsqueda de Lucene utilizado por varios clientes. Resuelvo este problema haciendo del ''Servicio de búsqueda de Lucene'' un servicio web independiente que se ejecuta en su propio dominio de aplicación. Como ambos clientes acceden al mismo servicio web para buscar o actualizar el índice, puedo hacer que sea seguro para subprocesos con bloqueos en los indexadores de Lucene.

Aparte de eso, si desea mantenerlo en proceso, le sugiero que utilice los bloqueos de archivos para asegurarse de que solo un cliente pueda escribir en el índice.

Para lograr que use un nuevo índice, creo uno en el lateral y luego le digo al servicio del Índice de Búsqueda que cambie para usar el nuevo índice mediante la eliminación segura de cualquier Indizador en el índice actual y el cambio de nombre de los directorios, por ejemplo

  • Index.Current> Index.Old
  • Index.New> Index.Current

Si tendrá varios escritores en diferentes procesos, y pasarán más de 10 segundos escribiendo sus cambios en el índice (lo que causará que los escritores en espera finalicen el tiempo de espera), entonces puede sincronizar el acceso entre los procesos utilizando Mutexes con nombre . Simplemente abra / cree un Mutex con el mismo nombre global en cada aplicación, y use Mutex.WaitOne antes de escribir, y Mutex.ReleaseMutex después de escribir.

var mut = Mutex.OpenExisting("myUniqueMutexName"); // wrap in try..catch to create if non-existent mut.WaitOne(); try { // write logic } finally { // recover from write failure mut.ReleaseMutex(); }

Probablemente sea mejor hacer el Mutex un singleton ya que son un poco caros de construir.

Actualización (por comentario):

Si los procesos están en máquinas separadas, creo que su única alternativa es colocar su propio sistema de archivos de bloqueo (usando archivos de bloqueo antiguos) para sincronizar el acceso. Como el bloqueo incorporado utiliza los bloqueos del sistema de archivos de todos modos, en realidad recomendaría que solo aumente el tiempo de espera de IndexWriter cada vez que construya uno.

var iw = new IndexWriter(); iw.WRITE_LOCK_TIMEOUT = 60000;

También puedes seguir intentando un número específico de veces.

var committed = false; var attempts = 0; while(!committed && attempts < 10) { try { // write logic committed = true; } catch (LockObtainFailedException) { attempts++; } }