Menu
Open source RSS

Client

Client is a Redis client to interact with a Redis server, sentinel, or cluster. It exposes a promise-based API, which users can interact with in an asynchronous manner.

Though the API intends to be thorough and extensive, it does not expose the whole Redis API. Instead, the intent is to expose Redis for use cases most appropriate to k6.

Usage

Single-node server

You can create a new Client instance that connects to a single Redis server by passing a URL string. It must be in the format:

redis[s]://[[username][:password]@][host][:port][/db-number]

Here’s an example of a URL string that connects to a Redis server running on localhost, on the default port (6379), and using the default database (0):

JavaScript
import redis from 'k6/experimental/redis';

const client = new redis.Client('redis://localhost:6379');

A client can also be instantiated using an options object to support more complex use cases, and for more flexibility:

JavaScript
import redis from 'k6/experimental/redis';

const client = new redis.Client({
  socket: {
    host: 'localhost',
    port: 6379,
  },
  username: 'someusername',
  password: 'somepassword',
});

TLS

You can configure a TLS connection in a couple of ways.

If the server has a certificate signed by a public Certificate Authority, you can use the rediss URL scheme:

JavaScript
import redis from 'k6/experimental/redis';

const client = new redis.Client('rediss://example.com');

Otherwise, you can supply your own self-signed certificate in PEM format using the socket.tls object:

JavaScript
import redis from 'k6/experimental/redis';

const client = new redis.Client({
  socket: {
    host: 'localhost',
    port: 6379,
    tls: {
      ca: [open('ca.crt')],
    },
  },
});

Note that for self-signed certificates, k6’s insecureSkipTLSVerify option must be enabled (set to true).

TLS client authentication (mTLS)

You can also enable mTLS by setting two additional properties in the socket.tls object:

JavaScript
import redis from 'k6/experimental/redis';

const client = new redis.Client({
  socket: {
    host: 'localhost',
    port: 6379,
    tls: {
      ca: [open('ca.crt')],
      cert: open('client.crt'), // client certificate
      key: open('client.key'), // client private key
    },
  },
});

Cluster client

You can connect to a cluster of Redis servers by using the cluster configuration property, and passing 2 or more node URLs:

JavaScript
import redis from 'k6/experimental/redis';

const client = new redis.Client({
  cluster: {
    // Cluster options
    maxRedirects: 3,
    readOnly: true,
    routeByLatency: true,
    routeRandomly: true,
    nodes: ['redis://host1:6379', 'redis://host2:6379'],
  },
});

Or the same as above, but passing socket objects to the nodes array instead of URLs:

JavaScript
import redis from 'k6/experimental/redis';

const client = new redis.Client({
  cluster: {
    nodes: [
      {
        socket: {
          host: 'host1',
          port: 6379,
        },
      },
      {
        socket: {
          host: 'host2',
          port: 6379,
        },
      },
    ],
  },
});

Sentinel client

A Redis Sentinel provides high availability features, as an alternative to a Redis cluster.

You can connect to a sentinel instance by setting additional options in the object passed to the Client constructor:

JavaScript
import redis from 'k6/experimental/redis';

const client = new redis.Client({
  username: 'someusername',
  password: 'somepassword',
  socket: {
    host: 'localhost',
    port: 6379,
  },
  // Sentinel options
  masterName: 'masterhost',
  sentinelUsername: 'sentineluser',
  sentinelPassword: 'sentinelpass',
});

Real world example

JavaScript
import { check } from 'k6';
import http from 'k6/http';
import redis from 'k6/experimental/redis';
import exec from 'k6/execution';
import { textSummary } from 'https://jslib.k6.io/k6-summary/0.0.2/index.js';

export const options = {
  scenarios: {
    redisPerformance: {
      executor: 'shared-iterations',
      vus: 10,
      iterations: 200,
      exec: 'measureRedisPerformance',
    },
    usingRedisData: {
      executor: 'shared-iterations',
      vus: 10,
      iterations: 200,
      exec: 'measureUsingRedisData',
    },
  },
};

// Instantiate a new redis client
const redisClient = new redis.Client(`redis://localhost:6379`);

// Prepare an array of crocodile ids for later use
// in the context of the measureUsingRedisData function.
const crocodileIDs = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

export async function measureRedisPerformance() {
  // VUs are executed in a parallel fashion,
  // thus, to ensure that parallel VUs are not
  // modifying the same key at the same time,
  // we use keys indexed by the VU id.
  const key = `foo-${exec.vu.idInTest}`;

  await redisClient.set(key, 1);
  await redisClient.incrBy(key, 10);
  const value = await redisClient.get(key);
  if (value !== '11') {
    throw new Error('foo should have been incremented to 11');
  }

  await redisClient.del(key);
  if ((await redisClient.exists(key)) !== 0) {
    throw new Error('foo should have been deleted');
  }
}

export async function setup() {
  await redisClient.sadd('crocodile_ids', ...crocodileIDs);
}

export async function measureUsingRedisData() {
  // Pick a random crocodile id from the dedicated redis set,
  // we have filled in setup().
  const randomID = await redisClient.srandmember('crocodile_ids');
  const url = `https://test-api.k6.io/public/crocodiles/${randomID}`;
  const res = await http.asyncRequest('GET', url);

  check(res, { 'status is 200': (r) => r.status === 200 });

  await redisClient.hincrby('k6_crocodile_fetched', url, 1);
}

export async function teardown() {
  await redisClient.del('crocodile_ids');
}

export function handleSummary(data) {
  redisClient
    .hgetall('k6_crocodile_fetched')
    .then((fetched) => Object.assign(data, { k6_crocodile_fetched: fetched }))
    .then((data) => redisClient.set(`k6_report_${Date.now()}`, JSON.stringify(data)))
    .then(() => redisClient.del('k6_crocodile_fetched'));

  return {
    stdout: textSummary(data, { indent: '  ', enableColors: true }),
  };
}

API

Key value methods

MethodRedis commandDescription
Client.set(key, value, expiration)SETSet key to hold value, with a time to live equal to expiration.
Client.get(key)GETGet the value of key.
Client.getSet(key, value)GETSETAtomically sets key to value and returns the old value stored at key.
Client.del(keys)DELRemoves the specified keys.
Client.getDel(key)GETDELGet the value of key and delete the key.
Client.exists(keys)EXISTSReturns the number of key arguments that exist.
Client.incr(key)INCRIncrements the number stored at key by one.
Client.incrBy(key, increment)INCRBYIncrements the number stored at key by increment.
Client.decr(key)DECRDecrements the number stored at key by one.
Client.decrBy(key, decrement)DECRBYDecrements the number stored at key by decrement.
Client.randomKey()RANDOMKEYReturns a random key’s value.
Client.mget(keys)MGETReturns the values of all specified keys.
Client.expire(key, seconds)EXPIRESets a timeout on key, after which the key will automatically be deleted.
Client.ttl(key)TTLReturns the remaining time to live of a key that has a timeout.
Client.persist(key)PERSISTRemoves the existing timeout on key.

List methods

MethodRedis commandDescription
Client.lpush(key, values)LPSUHInserts all the specified values at the head of the list stored at key.
Client.rpush(key, values)RPUSHInserts all the specified values at the tail of the list stored at key.
Client.lpop(key)LPOPRemoves and returns the first element of the list stored at key.
Client.rpop(key)RPOPRemoves and returns the last element of the list stored at key.
Client.lrange(key, start, stop)LRANGEReturns the specified elements of the list stored at key.
Client.lindex(key, start, stop)LINDEXReturns the specified element of the list stored at key.
Client.lset(key, index, element)LSETSets the list element at index to element.
Client.lrem(key, count, value)LREMRemoves the first count occurrences of value from the list stored at key.
Client.llen(key)LLENReturns the length of the list stored at key.

Hash methods

MethodRedis commandDescription
Client.hset(key, field, value)HSETSets the specified field in the hash stored at key to value.
Client.hsetnx(key, field, value)HSETNXSets the specified field in the hash stored at key to value, only if field does not yet exist.
Client.hget(key, field)HGETReturns the value associated with field in the hash stored at key.
Client.hdel(key, fields)HDELDeletes the specified fields from the hash stored at key.
Client.hgetall(key)HGETALLReturns all fields and values of the hash stored at key.
Client.hkeys(key)HKEYSReturns all fields of the hash stored at key.
Client.hvals(key)HVALSReturns all values of the hash stored at key.
Client.hlen(key)HLENReturns the number of fields in the hash stored at key.
Client.hincrby(key, field, increment)HINCRBYIncrements the integer value of field in the hash stored at key by increment.

Set methods

MethodRedis commandDescription
Client.sadd(key, members)SADDAdds the specified members to the set stored at key.
Client.srem(key, members)SREMRemoves the specified members from the set stored at key.
Client.sismember(key, member)SISMEMBERReturns if member is a member of the set stored at key.
Client.smembers(key)SMEMBERSReturns all the members of the set values stored at keys.
Client.srandmember(key)SRANDMEMBERReturns a random element from the set value stored at key.
Client.spop(key)SPOPRemoves and returns a random element from the set value stored at key.

Miscellaneous

MethodDescription
Client.sendCommand(command, args)Send a command to the Redis server.