full-text-search cluster - Fragmentos y réplicas en Elasticsearch




settings shards (7)

Estoy tratando de entender qué fragmento y réplica hay en Elasticsearch, pero no logro entenderlo. Si descargo Elasticsearch y ejecuto el script, entonces, por lo que sé, he iniciado un clúster con un solo nodo. Ahora este nodo (mi PC) tiene 5 fragmentos (?) Y algunas réplicas (?).

¿Qué son, tengo 5 duplicados del índice? Si es así, ¿por qué? Podría necesitar alguna explicación.


Answers

Si realmente no te gusta verlo amarillo. puede establecer el número de réplicas para que sea cero:

curl -XPUT 'localhost:9200/_settings' -d '
{
    "index" : {
        "number_of_replicas" : 0
    }
}
'

Tenga en cuenta que debe hacer esto solo en su cuadro de desarrollo local.


Un índice se divide en fragmentos para distribuirlos y escalarlos.

Las réplicas son copias de los fragmentos y proporcionan confiabilidad si se pierde un nodo. A menudo hay confusión en este número porque el número de réplicas == 1 significa que el grupo debe tener la copia principal y replicada del fragmento disponible para estar en estado verde.

Para poder crear réplicas, debe tener al menos 2 nodos en su clúster.

Puede encontrar las definiciones aquí más fáciles de entender: http://www.elasticsearch.org/guide/reference/glossary/

Saludos cordiales, Paul


Trataré de explicar con un ejemplo real, ya que la respuesta y las respuestas que recibiste no parecen ayudarte.

Cuando descarga elasticsearch y lo inicia, crea un nodo elasticsearch que intenta unirse a un clúster existente si está disponible o crea uno nuevo. Digamos que creó su propio nuevo clúster con un solo nodo, el que acaba de iniciar. No tenemos datos, por lo tanto necesitamos crear un índice.

Cuando crea un índice (un índice se crea automáticamente cuando también indexa el primer documento) puede definir de qué fragmentos se compondrá. Si no especifica un número, tendrá el número predeterminado de fragmentos: 5 primarios. Qué significa eso?

Significa que elasticsearch creará 5 fragmentos primarios que contendrán sus datos:

 ____    ____    ____    ____    ____
| 1  |  | 2  |  | 3  |  | 4  |  | 5  |
|____|  |____|  |____|  |____|  |____|

Cada vez que indexe un documento, elasticsearch decidirá qué fragmento primario debe contener ese documento y lo indexará allí. Los fragmentos primarios no son una copia de los datos, ¡son los datos! Tener varios fragmentos ayuda a aprovechar el procesamiento paralelo en una sola máquina, pero el punto es que si iniciamos otra instancia de elasticsearch en el mismo clúster, los fragmentos se distribuirán de manera uniforme sobre el clúster.

El nodo 1 contendrá entonces, por ejemplo, solo tres fragmentos:

 ____    ____    ____ 
| 1  |  | 2  |  | 3  |
|____|  |____|  |____|

Dado que los dos fragmentos restantes se han movido al nodo recién iniciado:

 ____    ____
| 4  |  | 5  |
|____|  |____|

¿Por qué pasó esto? Porque elasticsearch es un motor de búsqueda distribuido y de esta manera puede hacer uso de múltiples nodos / máquinas para administrar grandes cantidades de datos.

Cada índice de elasticsearch se compone de al menos un fragmento primario, ya que es donde se almacenan los datos. Sin embargo, cada fragmento tiene un costo, por lo tanto, si tiene un solo nodo y no tiene un crecimiento previsible, simplemente quédese con un solo fragmento primario.

Otro tipo de fragmento es una réplica. El valor predeterminado es 1, lo que significa que todos los fragmentos primarios se copiarán en otro fragmento que contendrá los mismos datos. Las réplicas se utilizan para aumentar el rendimiento de búsqueda y para la conmutación por error. Nunca se asignará un fragmento de réplica en el mismo nodo donde se encuentra el primario relacionado (sería como colocar una copia de seguridad en el mismo disco que los datos originales).

De vuelta a nuestro ejemplo, con 1 réplica tendremos el índice completo en cada nodo, ya que se asignarán 3 fragmentos de réplica en el primer nodo y contendrán exactamente los mismos datos que las primarias en el segundo nodo:

 ____    ____    ____    ____    ____
| 1  |  | 2  |  | 3  |  | 4R |  | 5R |
|____|  |____|  |____|  |____|  |____|

Lo mismo para el segundo nodo, que contendrá una copia de los fragmentos primarios en el primer nodo:

 ____    ____    ____    ____    ____
| 1R |  | 2R |  | 3R |  | 4  |  | 5  |
|____|  |____|  |____|  |____|  |____|

Con una configuración como esta, si un nodo se cae, todavía tiene todo el índice. Los fragmentos de réplica se convertirán automáticamente en primarios y el clúster funcionará correctamente a pesar del fallo del nodo, de la siguiente manera:

 ____    ____    ____    ____    ____
| 1  |  | 2  |  | 3  |  | 4  |  | 5  |
|____|  |____|  |____|  |____|  |____|

Como tiene "number_of_replicas":1 , las réplicas ya no se pueden asignar, ya que nunca se asignan en el mismo nodo donde se encuentra su primario. Es por eso que tendrá 5 fragmentos no asignados, las réplicas y el estado del clúster será YELLOW lugar de GREEN . No hay pérdida de datos, pero podría ser mejor ya que algunos fragmentos no se pueden asignar.

Tan pronto como el nodo que queda haya vuelto, se unirá al clúster de nuevo y las réplicas se asignarán de nuevo. El fragmento existente en el segundo nodo se puede cargar, pero deben estar sincronizados con los otros fragmentos, ya que las operaciones de escritura probablemente ocurrieron mientras el nodo estaba inactivo. Al final de esta operación, el estado del clúster se pondrá GREEN .

Espero que esto aclare las cosas para ti.


Casco:

  1. Al ser un servidor de búsqueda distribuido, ElasticSearch utiliza el concepto llamado Shard para distribuir documentos de índice en todos los nodos.
  2. Un index puede almacenar potencialmente una gran cantidad de datos que pueden exceder los límites de hardware de un single node
  3. Por ejemplo, un solo índice de mil millones de documentos que ocupan 1TB de espacio en disco puede no caber en el disco de un solo nodo o puede ser demasiado lento para atender las solicitudes de búsqueda desde un solo nodo solo.
  4. Para resolver este problema, Elasticsearch ofrece la capacidad de subdividir su índice en varias partes llamadas shards .
  5. Cuando crea un índice, simplemente puede definir el número de shards que desea.
  6. Documents se almacenan en shards y los fragmentos se asignan a los nodes de su cluster
  7. A medida que su cluster crece o se reduce, Elasticsearch migrará automáticamente los fragmentos entre nodes para que el cluster permanezca equilibrado.
  8. Un fragmento puede ser un primary shard o un replica shard .
  9. Cada documento en su índice pertenece a un single primary shard , por lo que la cantidad de fragmentos primarios que tiene determina la cantidad máxima de datos que puede contener su índice
  10. Un replica shard es solo una copia de un fragmento primario.

Réplica:

  1. Replica shard es la copia del primary Shard , para evitar la pérdida de datos en caso de falla del hardware.
  2. Elasticsearch permite hacer una o más copias de los fragmentos de su índice en lo que se conoce como fragmentos de réplica, o replicas para abreviar.
  3. Un index también se puede replicar en cero (es decir, sin réplicas) o más veces.
  4. El number of shards y réplicas se puede definir por índice en el momento en que se crea el índice.
  5. Después de crear el índice, puede cambiar el número de réplicas dinámicamente en cualquier momento, pero no cannot change the number of shards después del hecho.
  6. De forma predeterminada, a cada índice en Elasticsearch se le asignan 5 fragmentos primarios y 1 replica que significa que si tiene al menos dos nodos en su grupo, su índice tendrá 5 fragmentos primarios y otros 5 fragmentos de réplica (1 réplica completa) para un total de 10 fragmentos por índice.

Explicaré esto usando una palabra real de escenarios. Imagina que estás ejecutando un sitio web de comercio electrónico. A medida que usted se vuelve más popular, más vendedores y productos se agregan a su sitio web. Se dará cuenta de que la cantidad de productos que podría necesitar para indexar ha aumentado y es demasiado grande para caber en un disco duro de un nodo. Incluso si encaja en el disco duro, realizar una búsqueda lineal a través de todos los documentos en una máquina es extremadamente lento. un índice en un nodo no aprovechará la configuración de clúster distribuida en la que funciona la búsqueda de elastics.

Así que elasticsearch divide los documentos en el índice a través de múltiples nodos en el clúster. Cada división del documento se llama un fragmento. Cada nodo que lleva un fragmento de un documento tendrá solo un subconjunto del documento. Supongamos que tiene 100 productos y 5 fragmentos, cada uno tendrá 20 productos. Esta fragmentación de datos es lo que hace posible la búsqueda de baja latencia en elasticsearch. la búsqueda se realiza en paralelo en múltiples nodos. Los resultados son agregados y devueltos. Sin embargo, los fragmentos no proporcionan tolerancia a fallos. Esto significa que si algún nodo que contiene el fragmento está inactivo, el estado del clúster se vuelve amarillo. Lo que significa que algunos de los datos no están disponibles.

Para aumentar las réplicas de tolerancia a fallos entran en la imagen. Al anular la búsqueda elástica se crea una única réplica de cada fragmento. Estas réplicas siempre se crean en otro nodo donde el fragmento primario no reside. Por lo tanto, para que el sistema sea tolerante a fallos, es posible que deba aumentar la cantidad de nodos en su grupo y también depende de la cantidad de fragmentos de su índice. La fórmula general para calcular el número de nodos requeridos según las réplicas y los fragmentos es "número de nodos = número de fragmentos * (número de réplicas + 1)". La práctica estándar es tener al menos una réplica para la tolerancia a fallas.

Configurar el número de fragmentos es una operación estática, lo que significa que tiene que especificarlo cuando está creando un índice. Cualquier cambio posterior a eso requerirá una reindexación completa de los datos y llevará tiempo. Sin embargo, configurar la cantidad de réplicas es una operación dinámica y puede realizarse en cualquier momento después de la creación del índice también.

puede configurar el número de fragmentos y réplicas para su índice con el siguiente comando.

curl -XPUT 'localhost:9200/sampleindex?pretty' -H 'Content-Type: application/json' -d ' { "settings":{ "number_of_shards":2, "number_of_replicas":1 } } '


Un índice se divide en fragmentos para distribuirlos y escalarlos.

Las réplicas son copias de los fragmentos.

Un nodo es una instancia en ejecución de búsqueda elástica que pertenece a un clúster.

Un clúster consta de uno o más nodos que comparten el mismo nombre de clúster. Cada grupo tiene un solo nodo maestro que es elegido automáticamente por el grupo y que puede ser reemplazado si el nodo maestro actual falla.


Parece que Entity Framework 6 no admite la búsqueda de texto completo, pero hay una solución alternativa con los interceptores.

http://www.entityframework.info/Home/FullTextSearch

El enlace de actualización no funciona, así que aquí está el contenido original:

Microsoft TSQL admite consultas de texto completo mediante predicados (CONTAINS y FREETEXT)

Por ejemplo, tienes notas de tabla

Create table Notes (
    Id int Identity not null,
    NoteText text 
)

CREATE FULLTEXT CATALOG [Notes Data]

Cuando busca en esta tabla los registros que contienen la palabra 'John', debe emitir

SELECT TOP (10) 
* from gps.NOTES
WHERE contains(NoteText, '(john)') 

Desafortunadamente, el marco de Enity todavía no admite predicados de búsqueda de texto completo. Para EFv6, puede hacer una solución utilizando la intercepción.

La idea es envolver el texto de búsqueda con alguna palabra mágica durante el interior de la cadena. Contiene código y usa el interceptor para desenvolverlo justo antes de que se ejecute sql en SqlCommand.

Para empezar, vamos a crear la clase interceptor:

public class FtsInterceptor : IDbCommandInterceptor
{
    private const string FullTextPrefix = "-FTSPREFIX-";
    public static string Fts(string search)
    {
    return string.Format("({0}{1})", FullTextPrefix, search);
    }
    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }
    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }
    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        RewriteFullTextQuery(command);
    }
    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
    }
    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
        RewriteFullTextQuery(command);
    }
    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
    }
    public static void RewriteFullTextQuery(DbCommand cmd)
    {
        string text = cmd.CommandText;
        for (int i = 0; i < cmd.Parameters.Count; i++)
        {
            DbParameter parameter = cmd.Parameters[i];
            if (parameter.DbType.In(DbType.String, DbType.AnsiString, DbType.StringFixedLength, DbType.AnsiStringFixedLength))
            {
                if (parameter.Value == DBNull.Value)
                    continue;
                var value = (string)parameter.Value;
                if (value.IndexOf(FullTextPrefix) >= 0)
                {
                    parameter.Size = 4096;
                    parameter.DbType = DbType.AnsiStringFixedLength;
                    value = value.Replace(FullTextPrefix, ""); // remove prefix we added n linq query
                    value = value.Substring(1, value.Length - 2); // remove %% escaping by linq translator from string.Contains to sql LIKE
                    parameter.Value = value;
                    cmd.CommandText = Regex.Replace(text,
                    string.Format(
                    @"\[(\w*)\].\[(\w*)\]\s*LIKE\s*@{0}\s?(?:ESCAPE
                    N?'~')",parameter.ParameterName),
                    string.Format(@"contains([$1].[$2], @{0})",parameter.ParameterName));
                    if (text == cmd.CommandText)
                        throw new Exception("FTS was not replaced on: " + text);
                    text = cmd.CommandText;
                }
            }
        }
    }
}

Utilicé la función de extensión que se puede definir así:

static class LanguageExtensions
{
    public static bool In<T>(this T source, params T[] list)
    {
        return (list as IList<T>).Contains(source);
    }
}

Ahora vamos a componer una muestra de cómo usarlo. Necesitamos entidad clase Nota:

public class Note
{
    public int Id { get; set; }
    public string NoteText { get; set; }
}

Configuración de mapeo para ello:

public class NoteMap : EntityTypeConfiguration<Note>
{
    public NoteMap()
    {
        // Primary Key
        HasKey(t => t.Id);
    }
}

Y nuestro ancestro DbContext:

public class MyContext : DbContext
{
    static MyContext()
    {
        DbInterception.Add(new FtsInterceptor());
    }
    public MyContext(string nameOrConnectionString) : base(nameOrConnectionString)
    {
    }
    public DbSet<Note> Notes { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new NoteMap());
    }
}

Ahora estamos listos para usarlo. Vamos a buscar 'john':

class Program
{
    static void Main(string[] args)
    {
        var s = FtsInterceptor.Fts("john");
        using (var db = new MyContext("CONNSTRING"))
        {
            var q = db.Notes.Where(n => n.NoteText.Contains(s));
            var result = q.Take(10).ToList();
        }
    }
}




elasticsearch full-text-search