Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support redis cluster mode? #54

Open
Jaskey opened this issue Jul 9, 2018 · 4 comments
Open

Support redis cluster mode? #54

Jaskey opened this issue Jul 9, 2018 · 4 comments

Comments

@Jaskey
Copy link

Jaskey commented Jul 9, 2018

In production, we probably use cluster mode , but for now, OBF does not support this

@dvizzini
Copy link

dvizzini commented Mar 7, 2019

@Jaskey What did you end up doing?

I might take a stab at implementing a Redis cluster implementation.

@dvizzini
Copy link

dvizzini commented Mar 7, 2019

JedisCluster currently lacks a pipeline, and getting one in does not look too promising: redis/jedis#1455

@dvizzini
Copy link

dvizzini commented Mar 11, 2019

I think Ima make this into a PR:

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.exceptions.JedisMovedDataException;

import java.util.stream.Stream;

public class ClusteredRedisBloomFilterCache<K> {

    final private LoadingCache<K, BloomFilter<K>> bloomFilters;

    public ClusteredRedisBloomFilterCache(
            final JedisCluster jedisCluster,
            final int expectedElements,
            final double falsePositiveProbability
    ) {
        this.bloomFilters = Caffeine.newBuilder()
                .build(key -> {
                    final HostAndPort hostAndPort = getBloomfilterHostPort(jedisCluster, key);
                    return new FilterBuilder(expectedElements, falsePositiveProbability)
                            .name(key.toString())
                            .redisBacked(true)
                            .redisHost(hostAndPort.getHost())
                            .redisPort(hostAndPort.getPort())
                            .overwriteIfExists(false)
                            .buildBloomFilter();
                });
    }

    public ClusteredRedisBloomFilterCache(final JedisCluster jedisCluster) {
        this(jedisCluster, 1_000_000_000, 0.01);
    }

    public BloomFilter<K> get(K key) {
        return this.bloomFilters.get(key);
    }

    private HostAndPort getBloomfilterHostPort(final JedisCluster jedisCluster, final K key) {
        // Looked into cleaner methods. Jedis seems to hide all better ways.
        return jedisCluster.getClusterNodes().entrySet().stream()
                // Returns HostAndPort of redis node assigned to parameter key
                .flatMap(entry -> {
                    try (final Jedis jedis = entry.getValue().getResource()) {
                        try {
                            // Will fail if this redis node is not assigned to parameter key
                            jedis.get(key.toString());
                            // Will above did not fail, will return this redis node's HostAndPort
                            final String[] hostAndPort = entry.getKey().split(":");
                            final String host = hostAndPort[0];
                            final int port = Integer.valueOf(hostAndPort[1]);
                            return Stream.of(new HostAndPort(host, port));

                        } catch (final JedisMovedDataException jmde) {
                            // jedis.get failed. filtering out this redis node's HostAndPort
                            return Stream.empty();
                        }
                    }
                })
                // Should always find node in properly configured Redis cluster
                .findFirst().get();
    }
}

@thai-op
Copy link

thai-op commented Aug 30, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants