Skip to content

Instantly share code, notes, and snippets.

@ingenthr
Created August 16, 2018 17:47
Show Gist options
  • Save ingenthr/1ed8e8a76eddfdd02e6089ed83701bb6 to your computer and use it in GitHub Desktop.
Save ingenthr/1ed8e8a76eddfdd02e6089ed83701bb6 to your computer and use it in GitHub Desktop.
TAP snapshot
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC '-//OASIS//DTD DocBook XML V4.5//EN'
'http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd' [
<!ENTITY % every.entities SYSTEM "entities.ent">
%every.entities;
]>
<section id="membase-tap-protocol">
<title>TAP Protocol</title>
<para>
Overview
</para>
<para>
Tap provides a mechanism to observe from the outside data changes
going on within a memcached server.
</para>
<note>
<para>
In current releases of Membase Server, TAP is only implemented for
Membase bucket types, not for memcached buckets
</para>
</note>
<para>
Use Cases
</para>
<para>
Tap is a building block for lots of new types of things that would
like to react to changes within a memcached server without having to
actually modify memcached itself.
</para>
<para>
Replication
</para>
<para>
One simple use case is replication. Upon initial connect, a client
can ask for all existing data within a server as well as to be
notified as values change. We receive all data related to each item
that's being set, so just replaying that data on another node makes
replication an easy exercise.
</para>
<para>
Observation
</para>
<para>
Requesting a tap stream of only future changes makes it very easy to
see the types of things that are changing within your memcached
instance.
</para>
<para>
Secondary Layer Cache Invalidation
</para>
<para>
If you have frontends that are performing their own cache,
requesting a tap stream of future changes is useful for invalidating
items stored within this cache.
</para>
<para>
Ideally, such a stream would not include the actual data that had
changed. Today, all tap streams include full bodies, but specifying
new features that can be implemented by engines such as requesting
the omission of values is very straightforward.
</para>
<para>
External Indexing
</para>
<para>
A tap stream pointed at an index server (e.g. sphinx or solr) will
send all data changes to the index allowing for an always-up-to-date
full-text search index of your data.
</para>
<para>
vbucket transition
</para>
<para>
For the purposes of vbucket transfer between nodes, a new type of
tap request can be created that is every item stored in a vbucket
(or set of vbuckets) that is both existing and changing, but with
the ability to terminate the stream and cut-over ownership of the
vbucket once the last item is enqueued.
</para>
<para>
Protocol
</para>
<para>
A tap session begins by initiating a command from the client which
tells the server what we're interested in receiving and then the
server begins sending /client/ commands back across the connection
until the connection is terminated.
</para>
<para>
Moxi does not support proxy of the TAP sessions, so you have to
connect to the server you are interested in on port 11210. (Like all
other traffic, you must authenticate using
SASL to connect to the desired bucket)
</para>
<para>
Initial Base Message
</para>
<para>
A tap stream begins with a binary protocol message with the ID of
0x40 . The packet's key may specify a unique client identifier that
can be used to allow reconnects (resumable at the server's
discretion). A simple base message from a client referring to itself
as &quot;node1&quot; would appear as follows.
</para>
<programlisting>Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 80 | 40 ('@') | 00 | 05 |
+---------------+---------------+---------------+---------------+
4| 04 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
8| 00 | 00 | 00 | 09 |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
28| 6e ('n') | 6f ('o') | 64 ('d') | 65 ('e') |
+---------------+---------------+---------------+---------------+
32| 31 ('1') |
</programlisting>
<programlisting>Header breakdown
tap connect command
Field (offset) (value)
Magic (0) : 0x80 (PROTOCOL_BINARY_REQ)
Opcode (1) : 0x40
Key length (2,3) : 0x0005 (5)
Extra length (4) : 0x04
Data type (5) : 0x00
vbucket (6,7) : 0x0000 (0)
Total body (8-11) : 0x00000009 (9)
Opaque (12-15): 0x00000000
CAS (16-23): 0x0000000000000000
Flags (24-27): 0x00000000
Name (28-32): [node1]
</programlisting>
<para>
Options
</para>
<para>
Additional tap options may be specified as a 64-bit flags specifying
options. The flags will appear in the &quot;extras&quot; section of
the request packet. If omitted, it is assumed that all flags are 0.
</para>
<para>
Options may or may not have values. For options that do, the values
will appear in the body in the order they're defined (LSB -&gt;
MSB).
</para>
<para>
Backfill
</para>
<para>
BACKFILL ( =0x01=) contains a single 64-bit body that represents the
oldest entry (from epoch) you're interested in. Specifying a time in
the future (for the server you are connecting to), will cause it to
start streaming only current changes.
</para>
<para>
An example tap stream request that specifies a backfill of -1
(meaning future only) would look like this:
</para>
<programlisting>Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 80 | 40 ('@') | 00 | 05 |
+---------------+---------------+---------------+---------------+
4| 04 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
8| 00 | 00 | 00 | 11 |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 01 |
+---------------+---------------+---------------+---------------+
28| 6e ('n') | 6f ('o') | 64 ('d') | 65 ('e') |
+---------------+---------------+---------------+---------------+
32| 31 ('1') | ff | ff | ff |
+---------------+---------------+---------------+---------------+
36| ff | ff | ff | ff |
+---------------+---------------+---------------+---------------+
40| ff |
</programlisting>
<para>
Header breakdown
</para>
<para>
tap connect command
</para>
<para>
Field (offset) (value)
</para>
<para>
Magic (0) : 0x80 (PROTOCOL_BINARY_REQ)
</para>
<para>
Opcode (1) : 0x40
</para>
<para>
Key length (2,3) : 0x0005 (5)
</para>
<para>
Extra length (4) : 0x04
</para>
<para>
Data type (5) : 0x00
</para>
<para>
vbucket (6,7) : 0x0000 (0)
</para>
<para>
Total body (8-11) : 0x00000011 (17)
</para>
<para>
Opaque (12-15): 0x00000000
</para>
<para>
CAS (16-23): 0x0000000000000000
</para>
<para>
Flags (24-27): 0x00000001 backfill
</para>
<para>
Name (28-32): [node1]
</para>
<para>
Backfill date(33-40): 0xffffffffffffffff (-1)
</para>
<para>
Dump
</para>
<para>
DUMP ( =0x02=) contains no extra body and will cause the server to
transmit only existing items and disconnect after all of the items
have been transmitted.
</para>
<para>
An example tap stream request that specifies only dumping existing
records would look like this:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 40 ('@') | 00 | 05 |
+---------------+---------------+---------------+---------------+ 4|
04 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 09 |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 02 |
+---------------+---------------+---------------+---------------+
28| 6e ('n') | 6f ('o') | 64 ('d') | 65 ('e') |
+---------------+---------------+---------------+---------------+
</para>
<para>
32| 31 ('1') |
</para>
<para>
Header breakdown
</para>
<para>
tap connect command
</para>
<para>
Field (offset) (value)
</para>
<para>
Magic (0) : 0x80 (PROTOCOL_BINARY_REQ)
</para>
<para>
Opcode (1) : 0x40
</para>
<para>
Key length (2,3) : 0x0005 (5)
</para>
<para>
Extra length (4) : 0x04
</para>
<para>
Data type (5) : 0x00
</para>
<para>
vbucket (6,7) : 0x0000 (0)
</para>
<para>
Total body (8-11) : 0x00000009 (9)
</para>
<para>
Opaque (12-15): 0x00000000
</para>
<para>
CAS (16-23): 0x0000000000000000
</para>
<para>
Flags (24-27): 0x00000002 dump
</para>
<para>
Name (28-32): [node1]
</para>
<para>
Specify vbuckets
</para>
<para>
LIST_VBUCKETS ( =0x04=) contains a list of vbuckets and will cause
the server to transmit only notifications about changes in the
specified vbuckets.
</para>
<para>
An example tap stream request that specifies 3 vbuckets (vbucket 0,
1 and 2) would look like this:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 40 ('@') | 00 | 05 |
+---------------+---------------+---------------+---------------+ 4|
04 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 11 |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 04 |
+---------------+---------------+---------------+---------------+
28| 6e ('n') | 6f ('o') | 64 ('d') | 65 ('e') |
+---------------+---------------+---------------+---------------+
32| 31 ('1') | 00 | 03 | 00 |
+---------------+---------------+---------------+---------------+
36| 00 | 00 | 01 | 00 |
+---------------+---------------+---------------+---------------+
</para>
<para>
40| 02 |
</para>
<para>
Header breakdown
</para>
<para>
tap connect command
</para>
<para>
Field (offset) (value)
</para>
<para>
Magic (0) : 0x80 (PROTOCOL_BINARY_REQ)
</para>
<para>
Opcode (1) : 0x40
</para>
<para>
Key length (2,3) : 0x0005 (5)
</para>
<para>
Extra length (4) : 0x04
</para>
<para>
Data type (5) : 0x00
</para>
<para>
vbucket (6,7) : 0x0000 (0)
</para>
<para>
Total body (8-11) : 0x00000011 (17)
</para>
<para>
Opaque (12-15): 0x00000000
</para>
<para>
CAS (16-23): 0x0000000000000000
</para>
<para>
Flags (24-27): 0x00000004 list vbuckets
</para>
<para>
Name (28-32): [node1]
</para>
<para>
VBucket list (33-40): # listed (33-34): 0x0003 (3) vbucket (35-36):
0x0000 (0) vbucket (37-38): 0x0001 (1) vbucket (39-40): 0x0002 (2)
</para>
<para>
Transfer vbucket ownership
</para>
<para>
TAKEOVER_VBUCKETS ( =0x08=) contains no extra data and is used
together with LIST_VBUCKETS to transfer the ownership from the
server at the end of the dump of the server.
</para>
<para>
An example tap stream request that specifies 3 vbuckets (vbucket 0,
1 and 2) would look like this:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 40 ('@') | 00 | 05 |
+---------------+---------------+---------------+---------------+ 4|
04 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 11 |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 0c |
+---------------+---------------+---------------+---------------+
28| 6e ('n') | 6f ('o') | 64 ('d') | 65 ('e') |
+---------------+---------------+---------------+---------------+
32| 31 ('1') | 00 | 03 | 00 |
+---------------+---------------+---------------+---------------+
36| 00 | 00 | 01 | 00 |
+---------------+---------------+---------------+---------------+
</para>
<para>
40| 02 |
</para>
<para>
Header breakdown
</para>
<para>
tap connect command
</para>
<para>
Field (offset) (value)
</para>
<para>
Magic (0) : 0x80 (PROTOCOL_BINARY_REQ)
</para>
<para>
Opcode (1) : 0x40
</para>
<para>
Key length (2,3) : 0x0005 (5)
</para>
<para>
Extra length (4) : 0x04
</para>
<para>
Data type (5) : 0x00
</para>
<para>
vbucket (6,7) : 0x0000 (0)
</para>
<para>
Total body (8-11) : 0x00000011 (17)
</para>
<para>
Opaque (12-15): 0x00000000
</para>
<para>
CAS (16-23): 0x0000000000000000
</para>
<para>
Flags (24-27): 0x0000000c list vbuckets, takeover vbuckets
</para>
<para>
Name (28-32): [node1]
</para>
<para>
VBucket list (33-40): # listed (33-34): 0x0003 (3) vbucket (35-36):
0x0000 (0) vbucket (37-38): 0x0001 (1) vbucket (39-40): 0x0002 (2)
</para>
<para>
ACK
</para>
<para>
SUPPORT_ACK ( =0x10=) contains no extra data and is to notify the
tap server that we (the consumer) support sending an ack message
back to the tap server whenever the tap server asks for an ack.
</para>
<para>
An example tap stream request that specifies that we support acks
would look like this:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 40 ('@') | 00 | 05 |
+---------------+---------------+---------------+---------------+ 4|
04 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 09 |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 10 |
+---------------+---------------+---------------+---------------+
28| 6e ('n') | 6f ('o') | 64 ('d') | 65 ('e') |
+---------------+---------------+---------------+---------------+
</para>
<para>
32| 31 ('1') |
</para>
<para>
Header breakdown
</para>
<para>
tap connect command
</para>
<para>
Field (offset) (value)
</para>
<para>
Magic (0) : 0x80 (PROTOCOL_BINARY_REQ)
</para>
<para>
Opcode (1) : 0x40
</para>
<para>
Key length (2,3) : 0x0005 (5)
</para>
<para>
Extra length (4) : 0x04
</para>
<para>
Data type (5) : 0x00
</para>
<para>
vbucket (6,7) : 0x0000 (0)
</para>
<para>
Total body (8-11) : 0x00000009 (9)
</para>
<para>
Opaque (12-15): 0x00000000
</para>
<para>
CAS (16-23): 0x0000000000000000
</para>
<para>
Flags (24-27): 0x00000010 support ack
</para>
<para>
Name (28-32): [node1]
</para>
<para>
Keys only
</para>
<para>
KEYS_ONLY ( =0x20=) contains no extra data and is to notify the tap
server that we (the consumer) don't care about the values so we
would prefer that the tap server didn't send them. The server may
however decide to ignore your request.
</para>
<para>
An example tap stream request that specifies that we would prefer
the just the keys would look like this:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 40 ('@') | 00 | 05 |
+---------------+---------------+---------------+---------------+ 4|
04 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 09 |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 20 |
+---------------+---------------+---------------+---------------+
28| 6e ('n') | 6f ('o') | 64 ('d') | 65 ('e') |
+---------------+---------------+---------------+---------------+
</para>
<para>
32| 31 ('1') |
</para>
<para>
Header breakdown
</para>
<para>
tap connect command
</para>
<para>
Field (offset) (value)
</para>
<para>
Magic (0) : 0x80 (PROTOCOL_BINARY_REQ)
</para>
<para>
Opcode (1) : 0x40
</para>
<para>
Key length (2,3) : 0x0005 (5)
</para>
<para>
Extra length (4) : 0x04
</para>
<para>
Data type (5) : 0x00
</para>
<para>
vbucket (6,7) : 0x0000 (0)
</para>
<para>
Total body (8-11) : 0x00000009 (9)
</para>
<para>
Opaque (12-15): 0x00000000
</para>
<para>
CAS (16-23): 0x0000000000000000
</para>
<para>
Flags (24-27): 0x00000020 request keys only
</para>
<para>
Name (28-32): [node1]
</para>
<para>
Complex example
</para>
<para>
You may of course mix all of the fields:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 40 ('@') | 00 | 05 |
+---------------+---------------+---------------+---------------+ 4|
04 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 1d |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 35 ('5') |
+---------------+---------------+---------------+---------------+
28| 6e ('n') | 6f ('o') | 64 ('d') | 65 ('e') |
+---------------+---------------+---------------+---------------+
32| 31 ('1') | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
36| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
40| 05 | 00 | 05 | 00 |
+---------------+---------------+---------------+---------------+
44| 00 | 00 | 01 | 00 |
+---------------+---------------+---------------+---------------+
48| 02 | 00 | 03 | 00 |
+---------------+---------------+---------------+---------------+
</para>
<para>
52| 04 |
</para>
<para>
Header breakdown
</para>
<para>
tap connect command
</para>
<para>
Field (offset) (value)
</para>
<para>
Magic (0) : 0x80 (PROTOCOL_BINARY_REQ)
</para>
<para>
Opcode (1) : 0x40
</para>
<para>
Key length (2,3) : 0x0005 (5)
</para>
<para>
Extra length (4) : 0x04
</para>
<para>
Data type (5) : 0x00
</para>
<para>
vbucket (6,7) : 0x0000 (0)
</para>
<para>
Total body (8-11) : 0x0000001d (29)
</para>
<para>
Opaque (12-15): 0x00000000
</para>
<para>
CAS (16-23): 0x0000000000000000
</para>
<para>
Flags (24-27): 0x00000035 backfill, list vbuckets, support ack,
request keys only
</para>
<para>
Name (28-32): [node1]
</para>
<para>
Backfill date(33-40): 0x0000000000000005 (5)
</para>
<para>
VBucket list (41-52): # listed (41-42): 0x0005 (5) vbucket (43-44):
0x0000 (0) vbucket (45-46): 0x0001 (1) vbucket (47-48): 0x0002 (2)
vbucket (49-50): 0x0003 (3) vbucket (51-52): 0x0004 (4)
</para>
<para>
Response Commands
</para>
<para>
After initiating tap, a series of responses will begin streaming
commands back to the caller. These commands are similar to, but not
necessarily the same as existing commands. In particular, each
command includes a section of engine-specific data as well as a TTL
to avoid replication loops. [describe extended formats]
</para>
<para>
Mutation
</para>
<para>
All mutation events arrive as TAP_MUTATION ( =0x41=) events. These
are conceptualy similar to set commands. A mutation event for key
&quot;mykey&quot; with a value of &quot;value&quot; (no flags or
expiry) and a TTL of 255 would look like:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 41 ('A') | 00 | 05 |
+---------------+---------------+---------------+---------------+ 4|
10 | 00 | 00 | 66 ('f') |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 1a |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 03 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
28| ff | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
32| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
36| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
40| 6d ('m') | 79 ('y') | 6b ('k') | 65 ('e') |
+---------------+---------------+---------------+---------------+
44| 79 ('y') | 76 ('v') | 61 ('a') | 6c ('l') |
+---------------+---------------+---------------+---------------+
</para>
<para>
48| 75 ('u') | 65 ('e') |
</para>
<para>
Header breakdown Field (offset) (value) Magic (0) : 0x80
(PROTOCOL_BINARY_REQ) Opcode (1) : 0x41 (tap mutation) Key length
(2,3) : 0x0005 (5) Extra length (4) : 0x10 Data type (5) : 0x00
vbucket (6,7) : 0x0066 (102) Total body (8-11) : 0x0000001a (26)
Opaque (12-15): 0x00000000 (0) CAS (16-23): 0x0000000000000003 (3)
Engine priv. (24-25): 0x0000 (0) Flags (26-27): 0x0000 TTL (28): ff
Reserved (29): 00 Reserved (30): 00 Reserved (31): 00 Item Flags
(32-35): 0x00000000 Item Expiry (36-39): 0x00000000 Key (40-44):
[mykey] Value (45-49): [value]
</para>
<para>
Delete
</para>
<para>
TAP_DELETE ( =0x42=) may contain an engine specific section. A
typical packet for deletion of &quot;mykey&quot; with a TTL of 255
without any engine specific data would look like this:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 42 ('B') | 00 | 05 |
+---------------+---------------+---------------+---------------+ 4|
08 | 00 | 00 | 66 ('f') |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 0d |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
28| ff | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
32| 6d ('m') | 79 ('y') | 6b ('k') | 65 ('e') |
+---------------+---------------+---------------+---------------+
</para>
<para>
36| 79 ('y') |
</para>
<para>
Header breakdown Field (offset) (value) Magic (0) : 0x80
(PROTOCOL_BINARY_REQ) Opcode (1) : 0x42 (tap delete) Key length
(2,3) : 0x0005 (5) Extra length (4) : 0x08 Data type (5) : 0x00
vbucket (6,7) : 0x0066 (102) Total body (8-11) : 0x0000000d (13)
Opaque (12-15): 0x00000000 (0) CAS (16-23): 0x0000000000000000 (0)
Engine priv. (24-25): 0x0000 (0) Flags (26-27): 0x0000 TTL (28): ff
Reserved (29): 00 Reserved (30): 00 Reserved (31): 00 Key (32-36):
[mykey]
</para>
<para>
Flush
</para>
<para>
TAP_FLUSH ( =0x43=) may contain an engine specific section. A
typical flush packet with a TTL of 255 without any engine specific
data would look like this:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 43 ('C') | 00 | 00 |
+---------------+---------------+---------------+---------------+ 4|
08 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 08 |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
28| ff | 00 | 00 | 00 |
</para>
<para>
Header breakdown Field (offset) (value) Magic (0) : 0x80
(PROTOCOL_BINARY_REQ) Opcode (1) : 0x43 (tap flush) Key length (2,3)
: 0x0000 (0) Extra length (4) : 0x08 Data type (5) : 0x00 vbucket
(6,7) : 0x0000 (0) Total body (8-11) : 0x00000008 (8) Opaque
(12-15): 0x00000000 (0) CAS (16-23): 0x0000000000000000 (0) Engine
priv. (24-25): 0x0000 (0) Flags (26-27): 0x0000 TTL (28): ff
Reserved (29): 00 Reserved (30): 00 Reserved (31): 00
</para>
<para>
Opaque
</para>
<para>
The purpose of the TAP_OPAQUE ( =0x44=) packet is for engine writers
to be able to send control data to the consumer. A tap opaque packet
with 4 bytes of engine specific data (0xff 0xff 0xff 0xff for
vbucket 1023 and a TTL of 255 would look like this:
</para>
<para>
Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1
2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+ 0|
80 | 44 ('D') | 00 | 00 |
+---------------+---------------+---------------+---------------+ 4|
08 | 00 | 03 | ff |
+---------------+---------------+---------------+---------------+ 8|
00 | 00 | 00 | 0c |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 04 | 00 | 00 |
+---------------+---------------+---------------+---------------+
28| ff | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
32| ff | ff | ff | ff |
</para>
<para>
Header breakdown Field (offset) (value) Magic (0) : 0x80
(PROTOCOL_BINARY_REQ) Opcode (1) : 0x44 (tap opaque) Key length
(2,3) : 0x0000 (0) Extra length (4) : 0x08 Data type (5) : 0x00
vbucket (6,7) : 0x03ff (1023) Total body (8-11) : 0x0000000c (12)
Opaque (12-15): 0x00000000 (0) CAS (16-23): 0x0000000000000000 (0)
Engine priv. (24-25): 0x0004 (4) Flags (26-27): 0x0000 TTL (28): ff
Reserved (29): 00 Reserved (30): 00 Reserved (31): 00
</para>
<para>
Set vbucket
</para>
<para>
The purpose of the TAP_VBUCKET ( =0x45=) packet is to set the state
of a virtual bucket in the consumer (this is part of vbucket
takeover)
</para>
<programlisting>Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 80 | 45 ('E') | 00 | 00 |
+---------------+---------------+---------------+---------------+
4| 08 | 00 | 00 | 38 ('8') |
+---------------+---------------+---------------+---------------+
8| 00 | 00 | 00 | 0c |
+---------------+---------------+---------------+---------------+
12| 00 | 00 | 00 | 39 ('9') |
+---------------+---------------+---------------+---------------+
16| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
20| 00 | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
24| 00 | 04 | 00 | 01 |
+---------------+---------------+---------------+---------------+
28| ff | 00 | 00 | 00 |
+---------------+---------------+---------------+---------------+
32| 00 | 00 | 00 | 03 |
</programlisting>
<programlisting>Header breakdown
Field (offset) (value)
Magic (0) : 0x80 (PROTOCOL_BINARY_REQ)
Opcode (1) : 0x45 (tap vbucket set)
Key length (2,3) : 0x0000 (0)
Extra length (4) : 0x08
Data type (5) : 0x00
vbucket (6,7) : 0x0038 (56)
Total body (8-11) : 0x0000000c (12)
Opaque (12-15): 0x00000039 (57)
CAS (16-23): 0x0000000000000000 (0)
Engine priv. (24-25): 0x0000 (0)
Flags (26-27): 0x0001
</programlisting>
<programlisting> ack
TTL (28): ff
Reserved (29): 00
Reserved (30): 00
Reserved (31): 00
VB State (32-35): 0x00000003 (pending)
</programlisting>
<para>
Implementations and Samples
</para>
<para>
<command>vbucketmigrator</command> includes TAP client
implementations, and there is a sample Python client in the
membase engine source. There is also ongoing work on a specific
client for Java and Ruby. There is also a tutorial on accessing
TAP using the alpha libMembase. The behavior of TAP is defined in
the proposed memcached source.
</para>
</section>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment