How do I rename a bin in Aerospike?

How do I rename a bin in Aerospike?

Context

Some situations may require a bin to be renamed. There is no direct way of renaming a bin in Aerospike. However, this knowledge base article covers a few workarounds that can be considered with proper testing.

At a high level, renaming a bin will consist of moving its content to another bin before deleting it.

Methods

We will describe three different ways that can be used to rename a bin: using backup and restore, using client side coding and, finally, using a UDF.

1. Using Backup/Restore

This method consists of backing up the data using asbackup, change the bin name in the generated file(s), and use asrestore the restore and overwrite the data with the new bin name.

Let’s consider an example with a set named testset in namespace test where bin with name testbin1 should be renamed to testbinXYZ:

aql> select * from test.testset
+----------+----------+--------------------------------+-----------+-------+-------+
| testbin1 | testbin2 | {edigest}                      | {set}     | {ttl} | {gen} |
+----------+----------+--------------------------------+-----------+-------+-------+
| 21       | 31       | "2zqlwHxtxc4GoobPmO+6EXpySPY=" | "testset" | 84463 | 1     |
| 20       | 30       | "4M7pVgej+LLOXodwcH9hhzfN9i4=" | "testset" | 84460 | 2     |
| 22       | 32       | "oLZ8JibYJM+1FhHYbV1MA+6RFzo=" | "testset" | 84534 | 1     |
+----------+----------+--------------------------------+-----------+-------+-------+
  • Backup the data using asbackup:
asbackup -d backupdir -n test -s testset
  • Change the bin name using an editor (to be run from within the backupdir directory):
for f in `ls *.asb`; do sed -i 's/testbin1/testbinXYZ/g' $f; done
  • Restore with the -g option to ignore generation and -r to replace the record:
 asrestore -r -g -d backupdir

This would result in the generation getting incremented and the name of the bin testbin1 to be changed to testbinXYZ:

aql> select * from test.testset
+------------+----------+--------------------------------+-----------+-------+-------+
| testbinXYZ | testbin2 | {edigest}                      | {set}     | {ttl} | {gen} |
+------------+----------+--------------------------------+-----------+-------+-------+
| 21         | 31       | "2zqlwHxtxc4GoobPmO+6EXpySPY=" | "testset" | 84375 | 2     |
| 20         | 30       | "4M7pVgej+LLOXodwcH9hhzfN9i4=" | "testset" | 84372 | 3     |
| 22         | 32       | "oLZ8JibYJM+1FhHYbV1MA+6RFzo=" | "testset" | 84515 | 2     |
+------------+----------+--------------------------------+-----------+-------+-------+

Note: This method may require stopping client write traffic to avoid records getting updated (between backup and restore) which could result in potential loss of interim updates (that would be overwritten by the restore).

2. Using code client side

You can write a code snippet, which would read the records (for example through a scan) and store them back, with the primary key and a new bin name.

Refer to the knowledge-base article on Using Keys and Digests in Aerospike.

3. Using a UDF

The following simple lua script will set the content of bin with name oldbin into a (new) bin with name newbin and set the value of oldbin to nil in order to delete it.

function RenameBin(r, oldbin, newbin)
	r[newbin] = r[oldbin]
	r[oldbin] = nil
	aerospike:update(r)
end

Let’s consider the following set named testset in namespace test, and let’s register and execute the above lua module on it:

aql> select * from test.testset
+--------+------+--------------------------------+-----------+-------+-------+
| oldbin | bin2 | {edigest}                      | {set}     | {ttl} | {gen} |
+--------+------+--------------------------------+-----------+-------+-------+
| 22     | 32   | "XErAYt0ueEhlD07VBdroi6mxmFY=" | "testset" | 86400 | 1     |
| 23     | 33   | "4nuTpeoUrmfwj1t6G1ogTZzaLYM=" | "testset" | 86400 | 1     |
| 21     | 31   | "9ZEkmG6WrRdbN0yUh5RbvK1Te3Q=" | "testset" | 86400 | 1     |
+--------+------+--------------------------------+-----------+-------+-------+
3 rows in set (0.318 secs)

OK

aql> register module './renamebin.lua'
OK, 1 module added.

aql> execute renamebin.RenameBin("oldbin","newbin")  ON test.testset
OK, Scan job (1821797917986546735) created.

aql> select * from test.testset
+------+--------+--------------------------------+-----------+-------+-------+
| bin2 | newbin | {edigest}                      | {set}     | {ttl} | {gen} |
+------+--------+--------------------------------+-----------+-------+-------+
| 32   | 22     | "XErAYt0ueEhlD07VBdroi6mxmFY=" | "testset" | 86400 | 2     |
| 33   | 23     | "4nuTpeoUrmfwj1t6G1ogTZzaLYM=" | "testset" | 86400 | 2     |
| 31   | 21     | "9ZEkmG6WrRdbN0yUh5RbvK1Te3Q=" | "testset" | 86400 | 2     |
+------+--------+--------------------------------+-----------+-------+-------+
3 rows in set (0.321 secs)

OK

Note: It is of course assumed that a bin with name newbin didn’t exist already on any of the records. If such a bin did exist, it will get overwritten. Further lua code can be written to check for this condition upfront.

Notes

  • The old bin name will still be counted in the total bin names quota. In order to erase it completely, you will need to follow the How to Clear Up Bin Names knowledge base article.

Keywords

ASRESTORE ASBACKUP UDF BIN RENAME

Timestamp

4 Oct 2018