4

Currently, our Redis set up involves Jedis + sharding. Scaling up and down involves adding/removing shards manually which is a lot of operational work. We are also heavily dependent on pipelining since we are doing a lot of writes per second.

Hence, we are looking into Redis cluster to automate the sharding process. However, one deal-breaker for us is that Jedis doesn't support pipelining with Redis cluster: https://groups.google.com/forum/#!msg/redis-db/4I0ELYnf3bk/Lrctk0ULm6AJ

We are aware of Codis which supports pipelining + automatic sharding, but it requires heavy operational work to maintain due to its dependency on Zookeeper. It is also a fork of Redis so it may not be updated with upstream changes. Most likely we will be using it if there are no good solutions to use pipelining with the official Redis cluster implementation.

Just wondering if pipelining is at all possible with the official Redis cluster? Maybe in the form of an alternative Redis client?

uohzxela
  • 613
  • 4
  • 14
  • 28
  • 1
    Yes, you can use pipeline with Redis cluster, if all keys belong to the same slot. [This](https://stackoverflow.com/questions/49179753/using-jedis-how-to-write-to-a-specific-slot-node-in-redis-cluster/49185542#49185542) might be helpful. – for_stack May 03 '18 at 04:34

3 Answers3

4

Yes you can use pipeline in cluster mode as long as key hashes to same keyslot (not node).

To achieve keys hashing to same slot you can use hash tags. TLDR - if you have curly brackets in your key {} hash function will only be applied to that part https://redis.io/docs/reference/cluster-spec/#hash-tags

In my particular case I needed to put countries and cities by id into the redis which totaled 150k records. This is how I did it (nodejs + ioredis):

if (countries.length && cities.length) {
  const pipelines = []
  for (let i = 0; i < 21; i++) {
    pipelines.push(redis.pipeline())
  }
  await Promise.all([
    Promise.map(countries, (country) => {
      const randomPipeline = pipelines[country.id % 21]
      randomPipeline.set(`country_${country.id}_{${country.id % 21}}`, JSON.stringify(country))
    }),
    Promise.map(cities, (city) => {
      const randomPipeline = pipelines[city.id % 21]
      randomPipeline.set(`city_${city.id}_{${city.id % 21}}`, JSON.stringify(city))
    })
    
])
  for (let i = 0; i < 21; i++) {
    await pipelines[i].exec()
  }
  console.log('Countries and cities in cache')
}
Zuum Dj
  • 86
  • 4
3

Cluster pipeline is not support by jedis release version yet, but there is contribution waiting to be merged now, refer https://github.com/xetorthio/jedis/pull/1455.

You can also write your own implementation refer to that, The basic idea is capturing all commands sent with pipeline, and replaying them for cluster redirecting, as when all keys belong to the same slot, pipeline in cluster can work well.

Mobility
  • 3,117
  • 18
  • 31
0

Just an update. We decided to use Lettuce as the Redis client. It's currently deployed to production and it's working great with ElastiCache Redis cluster mode so far. The key insight is that Lettuce enables automatic pipelining of commands via async I/O. We think this is a better approach since we don't have to write custom code to work around the Jedis limitation.

uohzxela
  • 613
  • 4
  • 14
  • 28