Tous les produits
Search
Centre de documentation

Tablestore:PlainBuffer

Dernière mise à jour :Aug 18, 2026

Par rapport à Protocol Buffers, PlainBuffer offre de meilleures performances pour la sérialisation et la désérialisation des petits objets. C'est pourquoi Tablestore utilise le format PlainBuffer pour structurer les données.

Cette rubrique s'adresse aux développeurs qui implémentent un SDK Tablestore personnalisé ou qui déboguent la transmission brute des données au niveau du protocole. Les développeurs d'applications utilisant un SDK existant n'ont pas besoin de comprendre le fonctionnement interne de PlainBuffer.

Définition du format

Un message PlainBuffer se compose d'un en-tête suivi d'une ou plusieurs lignes. Chaque ligne contient une section de clé primaire et une section de colonne d'attribut ; ces deux sections peuvent être facultatives selon l'opération (voir la grammaire ci-dessous). Les tags servent de délimiteurs de champ : chaque tag indique à l'analyseur syntaxique l'élément suivant, ce qui lui permet de parcourir le flux d'octets sans ambiguïté.

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)
                

Valeurs des tags

La plupart des tags sont codés sur un seul octet et marquent le début d'un champ ; tag_header occupe 4 octets. L'analyseur syntaxique lit le tag, identifie le champ suivant, lit le nombre d'octets approprié, puis passe au tag suivant.

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)
            

Valeurs ValueType

Valeurs valides pour value_type dans 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
            

Calcul de la somme de contrôle

Les sommes de contrôle utilisent l'algorithme CRC8. Le calcul suit cette logique :

  • Le nom, la valeur, le type et l'horodatage de chaque cellule contribuent à la somme de contrôle de cette cellule.

  • Le marqueur de suppression de chaque ligne contribue pour un seul octet : 0x1 si la ligne possède un marqueur de suppression, 0x0 sinon.

  • La somme de contrôle de la ligne est calculée en appliquant CRC8 aux sommes de contrôle individuelles des cellules, et non aux données brutes des cellules.

Implémentation Java :

Remarque

Le code suivant est extrait de $tablestore-4.2.1-sources/com/alicloud/openservices/tablestore/core/protocol/PlainBufferCrc8.java. Pour plus d'informations, consultez 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;
}
            

Exemple

La ligne suivante comporte deux colonnes de clé primaire et quatre colonnes d'attribut.

  • Colonnes de clé primaire :

    • [pk1:string:iampk]

    • [pk2:integer:100]

  • Colonnes d'attribut :

    • [column1:string:bad:1001]

    • [column2:integer:128:1002]

    • [column3:double:34.2:1003]

    • [column4:del_all_versions]

Encodage :

<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]

Lecture octet par octet de la première cellule de clé primaire :

Octets

Tag/champ

Signification

0x3

tag_cell

Début d'une cellule

0x4

tag_cell_name

Le nom de la cellule suit

0x3

value_type

VT_STRING — le nom est une chaîne

3

value_len

Le nom fait 3 octets de long

pk1

value_data

Nom de la cellule : pk1

0x5

tag_cell_value

La valeur de la cellule suit

0x3

value_type

VT_STRING — la valeur est une chaîne

5

value_len

La valeur fait 5 octets de long

iampk

value_data

Valeur de la cellule : iampk

_cell_checksum

tag_cell_checksum + CRC8

Somme de contrôle portant sur le nom, la valeur, le type et l'horodatage

La deuxième cellule de clé primaire suit la même structure, sauf que le type de valeur est 0x0 (VT_INTEGER) et que value_len vaut 8 (un entier 64 bits).

Les cellules d'attribut ajoutent un champ d'horodatage (0x7 = tag_cell_ts) après la valeur. La colonne column4 ne contient aucune valeur : le tag 0x6 (tag_cell_op) avec la valeur 1 indique une opération de suppression de toutes les versions.