Todos los productos
Search
Centro de documentos

Tablestore:PlainBuffer

Última actualización: Sep 03, 2026

En comparación con Protocol Buffers, PlainBuffer ofrece un mejor rendimiento en la serialización y resolución de objetos pequeños. Por esta razón, Tablestore utiliza PlainBuffer para formatear los datos.

Este documento está dirigido a desarrolladores que implementan un SDK personalizado de Tablestore o depuran la transmisión de datos sin procesar a nivel de protocolo. Los desarrolladores de aplicaciones que usan un SDK existente no necesitan comprender el funcionamiento interno de PlainBuffer.

Definición del formato

Un mensaje de PlainBuffer consta de un encabezado seguido de una o más filas. Cada fila contiene una sección de clave primaria y una sección de columnas de atributos; ambas pueden ser opcionales según la operación (consulte la gramática a continuación). Las etiquetas actúan como delimitadores de campos: cada etiqueta indica al analizador qué elemento sigue, lo que le permite avanzar por el flujo de bytes sin ambigüedades.

plainbuffer = tag_header row1  [row2]  [row3]
row = ( pk [attr] | [pk] attr | pk attr ) [tag_delete_marker] row_checksum;
pk = tag_pk cell_1 [cell_2] [cell_3]
attr  = tag_attr cell1 [cell_2] [cell_3]
cell = tag_cell cell_name [cell_value] [cell_op] [cell_ts] cell_checksum
cell_name = tag_cell_name  formated_value
cell_value = tag_cell_value formated_value
cell_op = tag_cell_op  cell_op_value
cell_ts = tag_cell_ts cell_ts_value
row_checksum = tag_row_checksum row_crc8
cell_checksum = tag_cell_checksum row_crc8

formated_value = value_type value_len value_data
value_type = int8
value_len = int32

cell_op_value = delete_all_version | delete_one_version
cell_ts_value = int64 
delete_all_version = 0x01 (1byte)
delete_one_version = 0x03 (1byte)
                

Valores de las etiquetas

La mayoría de las etiquetas son de un solo byte y marcan el inicio de un campo; tag_header ocupa 4 bytes. El analizador lee la etiqueta, determina qué campo continúa, lee la cantidad adecuada de bytes y avanza a la siguiente etiqueta.

tag_header = 0x75 (4byte)
tag_pk = 0x01 (1byte)
tag_attr = 0x02 (1byte)
tag_cell = 0x03 (1byte)
tag_cell_name = 0x04 (1byte)
tag_cell_value = 0x05 (1byte)
tag_cell_op = 0x06 (1byte)
tag_cell_ts = 0x07 (1byte)
tag_delete_marker = 0x08 (1byte)
tag_row_checksum = 0x09 (1byte)
tag_cell_checksum = 0x0A (1byte)
            

Valores de ValueType

Valores válidos para value_type en formated_value:

VT_INTEGER = 0x0
VT_DOUBLE = 0x1
VT_BOOLEAN = 0x2
VT_STRING = 0x3
VT_NULL = 0x6
VT_BLOB = 0x7
VT_INF_MIN = 0x9
VT_INF_MAX = 0xa
VT_AUTO_INCREMENT = 0xb
            

Cálculo de la suma de verificación

Las sumas de verificación usan CRC8. El cálculo sigue esta lógica:

  • El nombre, el valor, el tipo y la marca de tiempo de cada celda contribuyen a su suma de verificación.

  • El marcador de eliminación de cada fila aporta un solo byte: 0x1 si la fila tiene marcador de eliminación, o 0x0 en caso contrario.

  • La suma de verificación de la fila se calcula al ejecutar CRC8 sobre las sumas de verificación individuales de las celdas, no sobre los datos sin procesar de estas.

Implementación en Java:

Nota

El código a continuación se extrajo de $tablestore-4.2.1-sources/com/alicloud/openservices/tablestore/core/protocol/PlainBufferCrc8.java. Para obtener más información, consulte Installation.

public static byte getChecksum(byte crc, PlainBufferCell cell) throws IOException {

    if (cell.hasCellName()) {
        crc = crc8(crc, cell.getNameRawData());
    }

    if (cell.hasCellValue()) {
        if (cell.isPk()) {
            crc = cell.getPkCellValue().getChecksum(crc);
        } else {
            crc = cell.getCellValue().getChecksum(crc);
        }
    }

    if (cell.hasCellTimestamp()) {
        crc = crc8(crc, cell.getCellTimestamp());
    }

    if (cell.hasCellType()) {
        crc = crc8(crc, cell.getCellType());
    }

    return crc;
}

public static byte getChecksum(byte crc, PlainBufferRow row) throws IOException {
    for (PlainBufferCell cell : row.getPrimaryKey()) {
        crc = crc8(crc, cell.getChecksum());
    }

    for (PlainBufferCell cell : row.getCells()) {
        crc = crc8(crc, cell.getChecksum());
    }

    byte del = 0;
    if (row.hasDeleteMarker()) {
        del = (byte)0x1;
    }
    crc = crc8(crc, del);

    return crc;
}
            

Ejemplo

La fila a continuación tiene dos columnas de clave primaria y cuatro columnas de atributos.

  • Columnas de clave primaria:

    • [pk1:string:iampk]

    • [pk2:integer:100]

  • Columnas de atributos:

    • [column1:string:bad:1001]

    • [column2:integer:128:1002]

    • [column3:double:34.2:1003]

    • [column4:del_all_versions]

Codificación:

<The start position for headers>[0x75]
<The start position for primary key columns>[0x1]
  <Cell1>[0x3][0x4][0x3][3][pk1][0x5][0x3][5][iampk][_cell_checksum]
  <Cell2>[0x3][0x4][0x3][3][pk2][0x5][0x0][8][100][_cell_checksum]
<The start position for attribute columns>[0x2]
  <Cell1>[0x3][0x4][0x3][7][column1][0x5][0x3][3][bad][0x7][1001][_cell_checksum]
  <Cell2>[0x3][0x4][0x3][7][column2][0x5][0x0][8][128][0x7][1002][_cell_checksum]
  <Cell3>[0x3][0x4][0x3][7][column3][0x5][0x1][8][34.2][0x7][1003][_cell_checksum]
  <Cell4>[0x3][0x4][0x3][7][column4][0x6][1][_cell_checksum]
[_row_check_sum]

Lectura de la primera celda de clave primaria byte por byte:

Bytes

Etiqueta/campo

Significado

0x3

tag_cell

Inicio de una celda

0x4

tag_cell_name

Indica que sigue el nombre de la celda

0x3

value_type

VT_STRING — el nombre es una cadena

3

value_len

El nombre mide 3 bytes

pk1

value_data

Nombre de la celda: pk1

0x5

tag_cell_value

Indica que sigue el valor de la celda

0x3

value_type

VT_STRING — el valor es una cadena

5

value_len

El valor mide 5 bytes

iampk

value_data

Valor de la celda: iampk

_cell_checksum

tag_cell_checksum + CRC8

Suma de verificación del nombre, valor, tipo y marca de tiempo

La segunda celda de clave primaria sigue la misma estructura, salvo que el tipo de valor es 0x0 (VT_INTEGER) y value_len es 8 (un entero de 64 bits).

Las celdas de atributos agregan un campo de marca de tiempo (0x7 = tag_cell_ts) después del valor. column4 carece de valor: la etiqueta 0x6 (tag_cell_op) con valor 1 la identifica como una operación de eliminación de todas las versiones.