Skip to content

6. Distributed objects

Nikita Koksharov edited this page Sep 11, 2019 · 50 revisions

Each Redisson object bound to name which used as a key in Redis.

RMap map = redisson.getMap("mymap");
map.getName(); // = mymap

All operations with Redis keys are exposed by RKeys interface. Usage example:

RKeys keys = redisson.getKeys();

Iterable<String> allKeys = keys.getKeys();

Iterable<String> foundedKeys = keys.getKeysByPattern('key*');

long numOfDeletedKeys = keys.delete("obj1", "obj2", "obj3");

long deletedKeysAmount = keys.deleteByPattern("test?");

String randomKey = keys.randomKey();

long keysAmount = keys.count();

6.1. Object holder

Redis based distributed RBucket object for Java is an universal holder for any type of object.

It has Async, Reactive and RxJava2 interfaces. Maximum object size is 512MB

RBucket<AnyObject> bucket = redisson.getBucket("anyObject");
bucket.set(new AnyObject(1));
AnyObject obj = bucket.get();

bucket.trySet(new AnyObject(3));
bucket.compareAndSet(new AnyObject(4), new AnyObject(5));
bucket.getAndSet(new AnyObject(6));

Use RBuckets interface to execute batch operations over RBucket object:

RBuckets buckets = redisson.getBuckets();
List<RBucket<V>> foundBuckets = buckets.find("myBucket*");
Map<String, V> loadedBuckets = buckets.get("myBucket1", "myBucket2", "myBucket3");

Map<String, Object> map = new HashMap<>();
map.put("myBucket1", new MyObject());
map.put("myBucket2", new MyObject());

// sets all or nothing if some bucket is already exists
buckets.trySet(map);
// store all at once
buckets.set(map);

6.2. Binary stream holder

Redis based distributed RBinaryStream object as holder for binary stream. It's easy to use thanks to exposed InputStream and OutputStream objects. Maximum byte stream size is limited by Redis master node memory only.

RBinaryStream stream = redisson.getBinaryStream("anyStream");
byte[] content = ...
stream.set(content);
stream.getAndSet(content);
stream.trySet(content);
stream.compareAndSet(oldContent, content);

InputStream is = stream.getInputStream();
byte[] readBuffer = new byte[512];
is.read(readBuffer);

OutputStream os = stream.getOuputStream();
byte[] contentToWrite = ...
os.write(contentToWrite);

6.3. Geospatial holder

Redis based distributed RGeo object for Java is a holder for geospatial items.

It has Async, Reactive and RxJava2 interfaces.

RGeo<String> geo = redisson.getGeo("test");
geo.add(new GeoEntry(13.361389, 38.115556, "Palermo"), 
        new GeoEntry(15.087269, 37.502669, "Catania"));
geo.addAsync(37.618423, 55.751244, "Moscow");

Double distance = geo.dist("Palermo", "Catania", GeoUnit.METERS);
geo.hashAsync("Palermo", "Catania");
Map<String, GeoPosition> positions = geo.pos("test2", "Palermo", "test3", "Catania", "test1");
List<String> cities = geo.radius(15, 37, 200, GeoUnit.KILOMETERS);
Map<String, GeoPosition> citiesWithPositions = geo.radiusWithPosition(15, 37, 200, GeoUnit.KILOMETERS);

6.4. BitSet

Redis based distributed RBitSet object for Java has structure similar to java.util.BitSet and represents vector of bits that grows as needed. Size limited by Redis to 4 294 967 295 bits. It has Async, Reactive and RxJava2 interfaces.

RBitSet set = redisson.getBitSet("simpleBitset");
set.set(0, true);
set.set(1812, false);
set.clear(0);
set.addAsync("e");
set.xor("anotherBitset");

6.4.1. BitSet data partitioning (distributed roaring bitmap)

Redis based distributed BitSet data partitioning for Java available only in cluster mode and implemented by separate RClusteredBitSet object. It uses distributed implementation of roaring bitmap structure. Size is limited by whole Redis Cluster memory. More details about partitioning here.

RClusteredBitSet set = redisson.getClusteredBitSet("simpleBitset");
set.set(0, true);
set.set(1812, false);
set.clear(0);
set.addAsync("e");
set.xor("anotherBitset");

This feature available only in Redisson PRO edition.

6.5. AtomicLong

Redis based distributed RAtomicLong object for Java has structure similar to java.util.concurrent.atomic.AtomicLong object.

It has Async, Reactive and RxJava2 interfaces.

RAtomicLong atomicLong = redisson.getAtomicLong("myAtomicLong");
atomicLong.set(3);
atomicLong.incrementAndGet();
atomicLong.get();

6.6. AtomicDouble

Redis based distributed RAtomicDouble object for Java. It has Async, Reactive and RxJava2 interfaces.

RAtomicDouble atomicDouble = redisson.getAtomicDouble("myAtomicDouble");
atomicDouble.set(2.81);
atomicDouble.addAndGet(4.11);
atomicDouble.get();

6.7. Topic

Redis based distributed RTopic object for Java implements Publish / Subscribe mechanism. Allows to subscribe on event published through this object.

It has Async, Reactive and RxJava2 interfaces.

RTopic topic = redisson.getTopic("anyTopic");
topic.addListener(SomeObject.class, new MessageListener<SomeObject>() {
    @Override
    public void onMessage(String channel, SomeObject message) {
        //...
    }
});

// in other thread or JVM
RTopic topic = redisson.getTopic("anyTopic");
long clientsReceivedMessage = topic.publish(new SomeObject());

Topic listeners are resubscribed automatically during any reconnection to Redis or Redis server failover.

6.7.1. Topic pattern

Redis based distributed RPatternTopic object for Java allows to subscribe to multiple topics by specified glob-style pattern.
Pattern examples:

  • topic? subscribes to topic1, topicA ...
  • topic?_my subscribes to topic_my, topic123_my, topicTEST_my ...
  • topic[ae] subscribes to topica and topice only

It has Async, Reactive and RxJava2 interfaces.

// subscribe to all topics by `topic*` pattern
RPatternTopic topic1 = redisson.getPatternTopic("topic*");
int listenerId = topic1.addListener(Message.class, new PatternMessageListener<Message>() {
    @Override
    public void onMessage(String pattern, String channel, Message msg) {
         Assert.fail();
    }
});

Topic pattern listeners are resubscribed automatically during any reconnection to Redis or Redis server failover.

6.8. Bloom filter

Redis based distributed RBloomFilter bloom filter for Java. Number of contained bits is limited to 2^32.

RBloomFilter<SomeObject> bloomFilter = redisson.getBloomFilter("sample");
// initialize bloom filter with 
// expectedInsertions = 55000000
// falseProbability = 0.03
bloomFilter.tryInit(55000000L, 0.03);
bloomFilter.add(new SomeObject("field1Value", "field2Value"));
bloomFilter.add(new SomeObject("field5Value", "field8Value"));
bloomFilter.contains(new SomeObject("field1Value", "field8Value"));

6.8.1. Bloom filter data partitioning

Redis based distributed Bloom filter for Java with data partitioning support available only in cluster mode and implemented by separate RClusteredBloomFilter object. This implementation uses more efficient distributed Redis memory allocation algorithm. It allows to "shrink" memory space consumed by unused bits across all Redis nodes. State of each instance is partitioned across all nodes in Redis cluster. Number of contained bits is limited to 2^64. More details about partitioning here.

RClusteredBloomFilter<SomeObject> bloomFilter = redisson.getClusteredBloomFilter("sample");
// initialize bloom filter with 
// expectedInsertions = 255000000
// falseProbability = 0.03
bloomFilter.tryInit(255000000L, 0.03);
bloomFilter.add(new SomeObject("field1Value", "field2Value"));
bloomFilter.add(new SomeObject("field5Value", "field8Value"));
bloomFilter.contains(new SomeObject("field1Value", "field8Value"));

This feature available only in Redisson PRO edition.

6.9. HyperLogLog

Redis based distributed RHyperLogLog object for Java. Probabilistic data structure that lets you maintain counts of millions of items with extreme space efficiency.

It has Async, Reactive and RxJava2 interfaces.

RHyperLogLog<Integer> log = redisson.getHyperLogLog("log");
log.add(1);
log.add(2);
log.add(3);

log.count();

6.10. LongAdder

Redis based distributed LongAdder object for Java has structure similar to java.util.concurrent.atomic.LongAdder object. It maintains internal LongAdder object on client side and provides superior performance for both increment and decrement operations. Up to 12000x faster than similar AtomicLong object. Suitable for distributed metric objects.

RLongAdder atomicLong = redisson.getLongAdder("myLongAdder");
atomicLong.add(12);
atomicLong.increment();
atomicLong.decrement();
atomicLong.sum();

Object should be destroyed if it not used anymore, but it's not necessary to call destroy method if Redisson goes shutdown.

RLongAdder atomicLong = ...
atomicLong.destroy();

6.11. DoubleAdder

Redis based distributed DoubleAdder object for Java has structure similar to java.util.concurrent.atomic.DoubleAdder object. It maintains internal DoubleAdder object on client side and provides superior performance for both increment and decrement operations. Up to 12000x faster than similar AtomicDouble object. Suitable for distributed metric objects.

RLongDouble atomicDouble = redisson.getLongDouble("myLongDouble");
atomicDouble.add(12);
atomicDouble.increment();
atomicDouble.decrement();
atomicDouble.sum();

Object should be destroyed if it not used anymore, but it's not necessary to call destroy method if Redisson goes shutdown.

RLongDouble atomicDouble = ...
atomicDouble.destroy();

6.12. RateLimiter

Redis based distributed RateLimiter object for Java restricts the total rate of calls either from all threads regardless of Redisson instance or from all threads working with the same Redisson instance. Doesn't guarantee fairness.

It has Async, Reactive and RxJava2 interfaces.

RRateLimiter limiter = redisson.getRateLimiter("myLimiter");
// Initialization required only once.
// 5 permits per 2 seconds
limiter.trySetRate(RateType.OVERALL, 5, 2, RateIntervalUnit.SECONDS);
        
CountDownLatch latch = new CountDownLatch(2);
limiter.acquire(3);
// ...

Thread t = new Thread(() -> {
    limiter.acquire(2);
    // ...        
});
You can’t perform that action at this time.