Skip to content

SSDB module

Francesco Saverio Castellano edited this page Mar 21, 2020 · 34 revisions

This module allows to connect and use a SSDB server, or a SSDB cluster.
By design the module is NOT thread safe, therefore each worker must establish its own connection to the SSDB server or cluster by calling the connect function.
SSDB does not have have full cluster support like Redis, but it allows a node to be replicated by one or more copies of it. Replication in SSDB comes with two modes: SYNC or MIRROR.
This SSDB module makes it possible to use multiple instances of SSDB as a cluster. The resulting cluster provides:

  • scalability: this is guaranteed by a pre-sharding strategy. This strategy consists in deciding upfront to split data accross N shards (or parts), with each shard being managed by a single SSDB instance. With a k-v database like SSDB splitting evenly the data across the N shards is easy: because every command operates on a specific key then one can just implement a simple key hashing strategy to map each key to one of the shards (for instance with N shards one can compute the ID of the shard for a key by doing the crc16 of the key and then compute the modulo N of the result).
    Initially one can deploy all SSDB instances of the N shards on one single machine or on few machines. Then when scaling is needed, it is just a matter of moving the SSDB instances of some shards (and their corresponding data) to new machines. Obviosuly the level of scalability depends on number of shards decided at the beginning. It will not be feasible to increase the shards at any later stage (because it would require migrating too much data accross SSDB instances).
    If one starts with 10 shards whose SSDB instances are all deployed ona single machine, then at most the database will be able to scale by a factor of 10 (assuming that the new machines have the same capabilities as the initial one).
  • high availability and failover: this is guaranteed by SSDB replication using MIRROR mode and having two masters (primary and secondary) for each shard: MIRROR replication means that the two masters will always be perfect copies of each other. The SSDB module will always actively use ONLY one of them (initially the primary one). If the primary master becomes unavailable the module will automatically switch to the secondary master (automatic failover) and it will keep using that one until the primary ones comes back and is synced again.

SSDB.connect(array servers)
Connects to the SSDB cluster. The servers parameter is an array where each element represents a shard. Each shard element is itself an array that contains the SSDB servers for it (primary master, secondary master, etc.). Each individual server is also an array of two elements: the host (string) and the port (integer).
The following example shows how to connect to a SSDB cluster made of 3 shards, with each shard having a primary master and a secondary master. Initially when all SSDB instances are available, the module will connect only two the primary masters (represented by the IPs on the left ending with .101, .103, .105 and .107):

SSDB.connect([
      [["192.168.0.101", 8888], ["192.168.0.102", 8888]]
      [["192.168.0.103", 8888], ["192.168.0.104", 8888]]
      [["192.168.0.105", 8888], ["192.168.0.106", 8888]]
      [["192.168.0.107", 8888], ["192.168.0.108", 8888]]
]);

The following code shows how to connect to a SSDB cluster made of only one shard running on two instances (primary and secondary masters for the single shard). In this case scalability will only be possible by improving the capabilities of the machines the runs the SSDB instance:

SSDB.connect([
      [["192.168.0.101", 8888], ["192.168.0.102", 8888]]
]);

Finally, the following code shows how to connect to a single SSDB instance (no sharding, no high-availabilty and no failover):

SSDB.connect([
      [["192.168.0.101", 8888]]
]);

 
SSDB.request(array command)
Executes command and returns the result. All elements in command must be strings, the first element is the name of the command, the second name is the key and all other elements are the command arguments.
Here below are some examples:

//sets k-v
SSDB.request(["set", "mykey", "myvalue"]);

//adds an element/score to a sorted set
SSDB.request(["zset", "mysortedset", "myvalue", "1000"]);

 
SSDB.nodeId(string key)
Returns the ID (index) of the shard that contains key.
Sometimes it might be useful to know what is the shard index for a specific key, this function can be used for this purpose.  
 
SSDB.nodeRequest(integer index, array command)
This is like SSDB.request but it allows to specify the shard index that corresponds to the SSDB instance that must execute the command.
Normally this function isn't needed, because the SSDB module takes care of automatically determining the correct SSDB instance for every command executed through SSDB.request by hashing the underlying key. Sometimes however it is needed to execute commands that do not have an underlying key (for instance scan commands that are used to iterate over all keys in the database). In this cases SSDB.nodeRequest must be used.  
 
SSDB.nodeForId(integer index)
Returns the active SSDB master instance for the request shard index.
The return value is an object that contains two properties: the host (string) and port of the SSDB instance.  
 

SSDB.pipelinedCommands(array commands)
This function allows sending multiple write commands with a single request and therefore it is an efficient way to execute several commands at once.
In a sharded k-v store, it only makes sense to use pipelines for commands that either share the same underlying key, or involve keys that belong to the same shard. This function instead can also be used with commands whose keys belong to different shards because the implementation takes care of grouping commands that are bound to the same shard and automatically executes individual pipelines, one for every shard involved.
The code in the following example connects to a SSDB cluster made of two shards and executes six commands using SSDB.pipelinedCommands. The commands will be split in two pipelines of three commands each, one of them will be sent to the instance on 192.168.1.100:8888 and the other one to 192.168.1.101:8888:

 SSDB.connect([
    [["192.168.1.100", 8888]],  
    [["192.168.1.101", 8888]]  
]);

var commands = [
      ["set", "key1", "value1"],
      ["set", "key2", "value2"],
      ["set", "key3", "value3"],
      ["set", "key4", "value4"],
      ["set", "key5", "value5"],
];

SSDB.pipelinedCommands(commands);
Clone this wiki locally