

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Cambiar las particiones de un flujo
<a name="kinesis-using-sdk-java-resharding"></a>

**importante**  
Puede volver a fragmentar su transmisión mediante la API. [UpdateShardCount](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_UpdateShardCount.html) También puede seguir realizando las divisiones y las fusiones como explicamos aquí.

Amazon Kinesis Data Streams permite *efectuar cambios en las particiones*, lo que le implica ajustar el número de particiones de la secuencia para adaptarse a los cambios en la velocidad del flujo de datos en la secuencia. Los cambios en las particiones se consideran operaciones avanzadas. Si es la primera vez que utiliza Kinesis Data Streams, vuelva a este tema después de familiarizarse con todos los demás aspectos de Kinesis Data Streams.

Existen dos tipos de operaciones de cambio de los fragmentos: división de fragmento y fusión de fragmentos. En una división, se divide un único fragmento en dos fragmentos. En una fusión, se combinan dos fragmentos en un único fragmento. Los cambios en los fragmentos siempre se realizan *en pares*, es decir, no se puede dividir en más de dos fragmentos en una sola operación y no se pueden fusionar más de dos fragmentos en una sola operación. El fragmento o par de fragmentos sobre los que actúa la operación de cambio se denominan fragmentos *principales*. El fragmento o par de fragmentos que surge como resultado de la operación de cambio se denominan fragmentos *secundarios*. 

La división aumenta el número de fragmentos en la secuencia, y por tanto incrementa la capacidad de datos de la misma. Dado que se le cobrará por fragmento, la división aumenta el costo de su secuencia. Del mismo modo, la fusión reduce el número de fragmentos en la secuencia, y por tanto disminuye la capacidad de datos y el costo de la misma. 

Los cambios en los fragmentos suele realizarlos una aplicación administrativa distinta de las aplicaciones productoras (put) y consumidoras (get). Una aplicación administrativa de este tipo supervisa el rendimiento general de la transmisión en función de las métricas proporcionadas por Amazon CloudWatch o en función de las métricas recopiladas de los productores y los consumidores. La aplicación administrativa también necesita un conjunto de permisos de IAM más amplio que el de los consumidores o los productores, ya que los consumidores y los productores normalmente no deberían necesitar acceder al material APIs utilizado para volver a fragmentarlo. Para más información sobre los permisos de IAM para Kinesis Data Streams, consulte [Control del acceso a los recursos de Amazon Kinesis Data Streams mediante IAM](controlling-access.md). 

Para más información sobre cambios en las particiones, consulte [¿Cómo puedo cambiar el número de particiones abiertas en Kinesis Data Streams?](https://aws.amazon.com/premiumsupport/knowledge-center/kinesis-data-streams-open-shards/)

**Topics**
+ [Decidir una estrategia para volver a particionar](kinesis-using-sdk-java-resharding-strategies.md)
+ [Dividir una partición](kinesis-using-sdk-java-resharding-split.md)
+ [Fusionar dos particiones](kinesis-using-sdk-java-resharding-merge.md)
+ [Completar la acción de volver a particionar](kinesis-using-sdk-java-after-resharding.md)

# Decidir una estrategia para volver a particionar
<a name="kinesis-using-sdk-java-resharding-strategies"></a>

El objetivo de realizar cambios en las particiones en Amazon Kinesis Data Streams es que la secuencia pueda adaptarse a los cambios en la velocidad del flujo de datos. Puede dividir fragmentos para aumentar la capacidad (y los costos) de la secuencia. Puede fusionar fragmentos para reducir el costo (y la capacidad) de la secuencia.

 Una forma de hacerlo sería dividir todas las particiones del flujo, lo que duplicaría su capacidad. Sin embargo, esto podría facilitar una capacidad adicional mayor que la que necesita realmente y, por tanto, crear costos innecesarios. 

También puede utilizar métricas para determinar cuáles son sus particiones *calientes* o *frías*, es decir, particiones que reciben muchos más datos o muchos menos datos de lo esperado. A continuación, puede dividir los fragmentos "calientes" de manera selectiva para aumentar la capacidad de las claves hash que se dirigen a esos fragmentos. Del mismo modo, podría fusionar fragmentos "fríos "para aprovechar mejor su capacidad.

Puede obtener algunos datos de rendimiento para su transmisión a partir de las CloudWatch métricas de Amazon que publica Kinesis Data Streams. Sin embargo, también puede recopilar sus propias métricas para las secuencias. Podría registrar los valores de las claves hash generadas por las claves de partición de sus registros de datos. Recuerde especificar la clave de partición en el momento en el que añada el registro a la secuencia. 

```
putRecordRequest.setPartitionKey( String.format( "myPartitionKey" ) );
```

Kinesis Data Streams [MD5](http://en.wikipedia.org/wiki/MD5)utiliza para calcular la clave hash a partir de la clave de partición. Como usted especifica la clave de partición para el registro, puede utilizarla MD5 para calcular el valor de la clave hash de ese registro y registrarlo. 

También puede registrar los fragmentos a IDs los que están asignados los registros de datos. Puede consultar la ID de fragmento utilizando el método `getShardId` del objeto `putRecordResults` que devuelve el método `putRecords` y el objeto `putRecordResult` que devuelve el método `putRecord`.

```
String shardId = putRecordResult.getShardId();
```

Con los valores del fragmento IDs y la clave hash, puede determinar qué fragmentos y claves hash reciben más o menos tráfico. A continuación, puede utilizar los cambios en los fragmentos para proporcionar más o menos capacidad, según proceda para estas claves.

# Dividir una partición
<a name="kinesis-using-sdk-java-resharding-split"></a>

Para dividir una partición en Amazon Kinesis Data Streams, debe especificar cómo deben redistribuirse los valores de clave hash de la partición principal a las particiones secundarias. Cuando añade un registro de datos a una secuencia, se asigna a un fragmento según un valor de clave hash. El valor de la clave hash es el [MD5](http://en.wikipedia.org/wiki/MD5)hash de la clave de partición que se especifica para el registro de datos en el momento de añadir el registro de datos a la transmisión. Los registros de datos que tengan la misma clave de partición también tienen el mismo valor de clave hash.

Los valores de clave hash posibles para un fragmento dado constituyen un conjunto de valores enteros positivos, ordenados y contiguos. Esta serie de posibles valores de clave hash viene dada por: 

```
shard.getHashKeyRange().getStartingHashKey();
shard.getHashKeyRange().getEndingHashKey();
```

Al dividir el fragmento especifica un valor de este rango. Ese valor de clave hash y todos los valores de clave hash superiores se distribuyen a uno de los fragmentos secundarios. Todos los valores de clave hash inferiores se distribuyen a los demás fragmentos secundarios. 

El código siguiente ilustra una operación de división de fragmentos que redistribuye las claves hash de manera uniforme entre cada uno de los fragmentos secundarios, básicamente dividiendo a la mitad el fragmento principal. Esta es solo una de las posibles formas de dividir el fragmento principal. Podría, por ejemplo, dividir el fragmento de forma que el tercio más bajo de las claves del fragmento principal vaya a uno de los fragmentos secundarios y los dos tercios más altos de las claves vayan al otro fragmento secundario. Sin embargo, para muchas aplicaciones, la división de fragmentos a la mitad resulta un enfoque eficaz. 

El código asume que `myStreamName` contiene el nombre de la secuencia y la variable de objeto `shard` contiene el fragmento que se ha de dividir. Empiece por crear una instancia de un nuevo objeto `splitShardRequest` y por introducir un nombre para la secuencia y una ID para el fragmento.

```
SplitShardRequest splitShardRequest = new SplitShardRequest();
splitShardRequest.setStreamName(myStreamName);
splitShardRequest.setShardToSplit(shard.getShardId());
```

Determine el valor de clave hash que está a medio camino entre los valores mínimo y máximo del fragmento. Este será el valor de clave hash inicial para el fragmento secundario que contendrá la mitad superior de las claves hash del fragmento principal. Especifique este valor en el método `setNewStartingHashKey`. Solo necesita especificar este valor. Kinesis Data Streams distribuye automáticamente las claves hash por debajo de este valor a la otra partición primaria creada por la división. El último paso consiste en llamar al método `splitShard` en el cliente de Kinesis Data Streams.

```
BigInteger startingHashKey = new BigInteger(shard.getHashKeyRange().getStartingHashKey());
BigInteger endingHashKey   = new BigInteger(shard.getHashKeyRange().getEndingHashKey());
String newStartingHashKey  = startingHashKey.add(endingHashKey).divide(new BigInteger("2")).toString();

splitShardRequest.setNewStartingHashKey(newStartingHashKey);
client.splitShard(splitShardRequest);
```

El primer paso tras este procedimiento se muestra en [Esperar a que un flujo se active de nuevo](kinesis-using-sdk-java-after-resharding.md#kinesis-using-sdk-java-resharding-wait-until-active). 

# Fusionar dos particiones
<a name="kinesis-using-sdk-java-resharding-merge"></a>

 Una operación de fusión toma dos fragmentos especificados y los combina en un único fragmento. Tras la fusión, el fragmento secundario recibe los datos de todos los valores de claves hash que cubrían los dos fragmentos principales. 

**Adyacencia de fragmentos**  
Para fusionar dos fragmentos, estos deben ser *adyacentes*. Se considera que dos fragmentos son adyacentes si la unión de los rangos de las claves hash de ambos forma un conjunto continuo sin huecos. Por ejemplo, supongamos que tiene dos fragmentos, uno con un rango de clave hash de 276...381 y el otro con un rango de clave hash de 382...454. Podría fusionar estos dos fragmentos en uno, que tendría un rango de clave hash de 276...454. 

Por tomar otro ejemplo, supongamos que tiene dos fragmentos, uno con un rango de clave hash de 276...381 y el otro con un rango de clave hash de 455...560. No es posible combinar estos dos fragmentos, ya que habría uno o varios fragmentos entre ellos abarcando el rango 382...454. 

El conjunto de todos los `OPEN` fragmentos de una transmisión, como grupo, siempre abarca todo el rango de valores de las claves hash. MD5 Para obtener más información sobre los estados de los fragmentos, como `CLOSED`, consulte [Tener en cuenta el direccionamiento de datos, persistencia de datos y estado de particiones tras los cambios en las particiones](kinesis-using-sdk-java-after-resharding.md#kinesis-using-sdk-java-resharding-data-routing). 

Para identificar fragmentos candidatos a la fusión, debe filtrar todos los que están en un estado `CLOSED`. Las particiones que están `OPEN` (es decir, no `CLOSED`) tienen un número secuencial final de `null`. Puede comprobar el número secuencial final de un fragmento con: 

```
if( null == shard.getSequenceNumberRange().getEndingSequenceNumber() ) 
{
  // Shard is OPEN, so it is a possible candidate to be merged.
}
```

Después de filtrar los fragmentos cerrados, ordene los fragmentos restantes por el valor de clave hash más alto que permita cada fragmento. Puede recuperar este valor mediante: 

```
shard.getHashKeyRange().getEndingHashKey();
```

 Si hay dos fragmentos adyacentes en la lista filtrada y ordenada, se pueden fusionar. 

**Código para la operación de fusión**  
 Con el siguiente código se fusionan dos fragmentos. El código asume que `myStreamName` contiene el nombre de la secuencia y las variables de objeto `shard1` y `shard2` contienen los dos fragmentos adyacentes que se han de fusionar.

Para la operación de fusión, comience por crear una instancia de un nuevo objeto `mergeShardsRequest`. Especifique el nombre de la secuencia con el método `setStreamName`. A continuación, especifique qué dos fragmentos quiere fusionar con los métodos `setShardToMerge` y `setAdjacentShardToMerge`. Por último, llame al método `mergeShards` en el cliente de Kinesis Data Streams para realizar la operación.

```
MergeShardsRequest mergeShardsRequest = new MergeShardsRequest();
mergeShardsRequest.setStreamName(myStreamName);
mergeShardsRequest.setShardToMerge(shard1.getShardId());
mergeShardsRequest.setAdjacentShardToMerge(shard2.getShardId());
client.mergeShards(mergeShardsRequest);
```

El primer paso tras este procedimiento se muestra en [Esperar a que un flujo se active de nuevo](kinesis-using-sdk-java-after-resharding.md#kinesis-using-sdk-java-resharding-wait-until-active).

# Completar la acción de volver a particionar
<a name="kinesis-using-sdk-java-after-resharding"></a>

Después de realizar cualquier tipo de procedimiento que implique cambios en las particiones en Amazon Kinesis Data Streams y antes de reanudar el procesamiento de registros normal, son necesarios otros procedimientos y consideraciones. Estos pasos se describen en las siguientes secciones.

**Topics**
+ [Esperar a que un flujo se active de nuevo](#kinesis-using-sdk-java-resharding-wait-until-active)
+ [Tener en cuenta el direccionamiento de datos, persistencia de datos y estado de particiones tras los cambios en las particiones](#kinesis-using-sdk-java-resharding-data-routing)

## Esperar a que un flujo se active de nuevo
<a name="kinesis-using-sdk-java-resharding-wait-until-active"></a>

Tras realizar una operación de cambio de partición, ya sea `splitShard` o `mergeShards`, tendrá que esperar a que el flujo vuelva a estar activo. El código que ha de usar es el mismo que al esperar a que una secuencia se active tras la [creación de una secuencia](kinesis-using-sdk-java-create-stream.md). Ese código es el siguiente:

```
DescribeStreamRequest describeStreamRequest = new DescribeStreamRequest();
describeStreamRequest.setStreamName( myStreamName );

long startTime = System.currentTimeMillis();
long endTime = startTime + ( 10 * 60 * 1000 );
while ( System.currentTimeMillis() < endTime ) 
{
  try {
    Thread.sleep(20 * 1000);
  } 
  catch ( Exception e ) {}
  
  try {
    DescribeStreamResult describeStreamResponse = client.describeStream( describeStreamRequest );
    String streamStatus = describeStreamResponse.getStreamDescription().getStreamStatus();
    if ( streamStatus.equals( "ACTIVE" ) ) {
      break;
    }
   //
    // sleep for one second
    //
    try {
      Thread.sleep( 1000 );
    }
    catch ( Exception e ) {}
  }
  catch ( ResourceNotFoundException e ) {}
}
if ( System.currentTimeMillis() >= endTime ) 
{
  throw new RuntimeException( "Stream " + myStreamName + " never went active" );
}
```

## Tener en cuenta el direccionamiento de datos, persistencia de datos y estado de particiones tras los cambios en las particiones
<a name="kinesis-using-sdk-java-resharding-data-routing"></a>

Kinesis Data Streams es un servicio de flujo de datos en tiempo real. Las aplicaciones deberían presuponer que los datos fluyen de forma continua a través de las particiones en el flujo. Cuando realiza cambios en los fragmentos, los registros de datos dirigidos a los fragmentos principales se redireccionan a los fragmentos secundarios en función de los valores de clave hash que asignan las claves de partición de los registros de datos. Sin embargo, los registros de datos que estaban en los fragmentos principales antes de los cambios permanecerán en dichos fragmentos. Las particiones principales no desaparecen cuando se producen los cambios. Persistirán junto con los datos que contenían antes de los cambios. Se puede acceder a los registros de datos de las particiones principales mediante las operaciones [`getShardIterator` y `getRecords`](developing-consumers-with-sdk.md#kinesis-using-sdk-java-get-data) de la API de Kinesis Data Streams, o a través de Kinesis Client Library.

**nota**  
Se puede obtener acceso a los registros de datos a partir del momento en el que se agregan a la secuencia y hasta el periodo de retención actual. Esto es así independientemente de los cambios en los fragmentos de la secuencia durante ese periodo. Para obtener más información acerca del periodo de retención de una secuencia, consulte [Cambiar el periodo de retención de datos](kinesis-extended-retention.md).

En el proceso de realizar cambios en los fragmentos, un fragmento principal cambia de un estado `OPEN` a un estado `CLOSED`, y después a un estado `EXPIRED`. 
+  **OPEN**: antes de una operación de cambio en los fragmentos, un fragmento principal tiene el estado `OPEN`, lo que significa que los registros de datos pueden tanto agregarse al fragmento como recuperarse desde él.
+  **CLOSED**: tras una operación de cambio en los fragmentos, el fragmento principal cambia a un estado `CLOSED`. Esto implica que ya no se agregan registros de datos al fragmento. Los registros de datos que se habrían añadido a este fragmento se agregarán a un fragmento secundario en su lugar. Sin embargo, se pueden seguir recuperando registros de datos desde el fragmento durante un tiempo limitado. 
+  **EXPIRED**: tras vencer el periodo de retención de la secuencia, todos los registros de datos del fragmento principal habrán caducado y ya no se podrá obtener acceso a ellos. En este punto, el propio fragmento cambia a un estado `EXPIRED`. Las llamadas a `getStreamDescription().getShards` para enumerar los fragmentos de la secuencia no incluyen los fragmentos `EXPIRED` en la lista de fragmentos que devuelve. Para obtener más información acerca del periodo de retención de una secuencia, consulte [Cambiar el periodo de retención de datos](kinesis-extended-retention.md).

Tras realizar los cambios en los fragmentos, y cuando la secuencia ha recuperado el estado `ACTIVE`, podría comenzar inmediatamente a leer datos en los fragmentos secundarios. Sin embargo, las particiones principales que permanecen tras realizar los cambios podrían seguir conteniendo datos que aún no se han leído y que se habrían agregado al flujo antes de los cambios. Si lee datos de los fragmentos secundarios antes de haber leído todos los datos de los fragmentos principales, podría leer datos de una clave hash determinada fuera del orden determinado por los números secuenciales de los registros de datos. Por lo tanto, suponiendo que el orden de los datos sea importante, después de un cambio en los fragmentos siempre se deben seguir leyendo datos de los fragmentos principales hasta que se agoten. Solo entonces debería empezar a leer datos de los fragmentos secundarios. Cuando `getRecordsResult.getNextShardIterator` devuelve `null`, indica que ya ha leído todos los datos del fragmento principal. 