Use cases of redis redisson collection of RList Rset RMap

  • 2021-10-16 01:44:14
  • OfStack

redis redisson Set Operation

Related classes and interfaces

Rlist: Linked list


public interface RList<V> extends List<V>, RExpirable, RListAsync<V>, RSortable<List<V>>, RandomAccess { 
    List<V> get(int... var1);              // Gets the specified node value  
    int addAfter(V var1, V var2);          // In var1 Add before var2
    int addBefore(V var1, V var2);         // In var1 Add after var2
    void fastSet(int var1, V var2);        // Modify var1 Only for var2
 
    List<V> readAll();                     // Get all the values of the linked list 
    RList<V> subList(int var1, int var2);  // Get var1 To var2 Sublinked list of 
    List<V> range(int var1);               // Return var1 Back linked list 
    List<V> range(int var1, int var2);     // Return var1 To var2 Linked list of 
 
    void trim(int var1, int var2);         // Reservation var1 To var2 The linked list at, and the rest is deleted  
    void fastRemove(int var1);             // Delete var1 Value at 
    boolean remove(Object var1, int var2); // Determine whether the element is deleted  
    <KOut, VOut> RCollectionMapReduce<V, KOut, VOut> mapReduce();  //mapreduce Operation  
}

RSet: Unordered Set


public interface RSet<V> extends Set<V>, RExpirable, RSetAsync<V>, RSortable<Set<V>> {  
    V removeRandom();
    Set<V> removeRandom(int var1);     // Delete an object  
    V random();
    Set<V> random(int var1);           // Random return object  
    boolean move(String var1, V var2); // Judgment set var1 Does it exist in var2 , similar contains() Method  
    Set<V> readAll();                  // Get all objects  
    int union(String... var1);         // Number of set union objects 
    Set<V> readUnion(String... var1);  // Set union  
    int diff(String... var1);          // Number of set difference set objects 
    Set<V> readDiff(String... var1);   // Set difference set 
 
    int intersection(String... var1);         // Number of objects intersected by sets 
    Set<V> readIntersection(String... var1);  // Set intersection  
    Iterator<V> iterator(int var1);
    Iterator<V> iterator(String var1, int var2);
    Iterator<V> iterator(String var1);        // Traversing the set 
 
    <KOut, VOut> RCollectionMapReduce<V, KOut, VOut> mapReduce();  
    RSemaphore getSemaphore(V var1);
    RCountDownLatch getCountDownLatch(V var1);
    RPermitExpirableSemaphore getPermitExpirableSemaphore(V var1);  // Semaphore 
 
    RLock getLock(V var1);
    RLock getFairLock(V var1);
    RReadWriteLock getReadWriteLock(V var1); // Lock operation 
 
    Stream<V> stream(int var1);
    Stream<V> stream(String var1, int var2);
    Stream<V> stream(String var1);          // Flow operation  
}

RMap: Key-value pairs


public interface RMap<K, V> extends ConcurrentMap<K, V>, RExpirable, RMapAsync<K, V> { 
    void loadAll(boolean var1, int var2);
    void loadAll(Set<? extends K> var1, boolean var2, int var3);
 
    V get(Object var1);                       // Get var1 Value of 
    V put(K var1, V var2);                    // Add Object 
    V putIfAbsent(K var1, V var2);            // Object does not exist  
    V replace(K var1, V var2);                // Replace object 
    boolean replace(K var1, V var2, V var3);  // Replace object  
    V remove(Object var1);                    // Remove Object 
    boolean remove(Object var1, Object var2); // Remove Object  
    void putAll(Map<? extends K, ? extends V> var1);
    void putAll(Map<? extends K, ? extends V> var1, int var2);   // Add Object 
 
    Map<K, V> getAll(Set<K> var1);                               // Get key In the collection var1 Key-value pairs in  
    int valueSize(K var1);                   //key For var1 Adj. value Size  
    V addAndGet(K var1, Number var2);        //key For var1 Adj. value Plus var2 
    long fastRemove(K... var1);              // Remove Object 
    boolean fastPut(K var1, V var2);         // Add Object 
    boolean fastReplace(K var1, V var2);     // Replace key For var1 The value of is var2
    boolean fastPutIfAbsent(K var1, V var2); // If it does not exist, set 
 
    Set<K> readAllKeySet();                  // Get all key , to set Formal return 
    Collection<V> readAllValues();           // Get all value , to collection Return 
    Set<Entry<K, V>> readAllEntrySet();      // Traversing key-value pairs 
    Map<K, V> readAllMap();                  // Collection form is converted to map Type 
 
    Set<K> keySet();
    Set<K> keySet(int var1);
    Set<K> keySet(String var1, int var2);
    Set<K> keySet(String var1);              // Get key Set 
 
    Collection<V> values();
    Collection<V> values(String var1);
    Collection<V> values(String var1, int var2);
    Collection<V> values(int var1);          // Get all value
 
    Set<Entry<K, V>> entrySet();
    Set<Entry<K, V>> entrySet(String var1);
    Set<Entry<K, V>> entrySet(String var1, int var2);
    Set<Entry<K, V>> entrySet(int var1);     // Traversing key-value pairs  
    <KOut, VOut> RMapReduce<K, V, KOut, VOut> mapReduce();  
    RSemaphore getSemaphore(K var1);
    RCountDownLatch getCountDownLatch(K var1);
    RPermitExpirableSemaphore getPermitExpirableSemaphore(K var1);  // Semaphore operation 
 
    RLock getLock(K var1);
    RLock getFairLock(K var1);
    RReadWriteLock getReadWriteLock(K var1);  // Lock operation 
}

Use sample


public class MyTest { 
    public static void main(String[] args){
        Config config=new Config();
        config.useSingleServer().setAddress("redis://******:6379").setPassword("123456"); 
        RedissonClient client= Redisson.create(config);
         RList<String> list=client.getList("list");
        for (int i=0;i<10;i++){
            list.add(" Gua Tian Li Xia  "+i);
        }
 
        list.readAll().forEach(System.out::println);
        System.out.println("list The number of is: "+list.size()+"\n"); 
        RSet<String> set=client.getSet("set");
        for (int i=0;i<10;i++){
            set.add(" Gua Tian Li Xia  "+i);
        }
 
        for (String s : set) {
            System.out.println(s);
        }
        System.out.println("set Is the size of: "+set.size()+"\n"); 
        RMap<Integer,String> map=client.getMap("map");
        for (int i=0;i<10;i++){
            map.put(i," Gua Tian Li Xia  "+i);
        }
 
        for (Map.Entry<Integer,String> entry:map.entrySet()){
            System.out.println(entry.getKey()+" ==> "+entry.getValue());
        }
        System.out.println("map Is the size of: "+map.size());
    }
}

Console output

Gua Tian Li Xia 0
Gua Tian Li Xia 1
Gua Tian Li Xia 2
Gua Tian Li Xia 3
Gua Tian Li Xia 4
Gua Tian Li Xia 5
Gua Tian Li Xia 6
Gua Tian Li Xia 7
Gua Tian Li Xia 8
Gua Tian Li Xia 9
The number of list is: 10

Gua Tian Li Xia 0
Gua Tian Li Xia 1
Gua Tian Li Xia 7
Gua Tian Li Xia 3
Gua Tian Li Xia 5
Gua Tian Li Xia 4
Gua Tian Li Xia 9
Gua Tian Li Xia 8
Gua Tian Li Xia 6
Gua Tian Li Xia 2
Size of set: 10

0 == > Gua Tian Li Xia 0
1 == > Gua Tian Li Xia 1
2 == > Gua Tian Li Xia 2
3 == > Gua Tian Li Xia 3
4 == > Gua Tian Li Xia 4
5 == > Gua Tian Li Xia 5
6 == > Gua Tian Li Xia 6
7 == > Gua Tian Li Xia 7
8 == > Gua Tian Li Xia 8
9 == > Gua Tian Li Xia 9
The size of map is: 10

Matters needing attention in using Redisson

Redisson is an Java in-memory data grid implemented on the basis of Redis. Compared with Jedis, which exposes the underlying operations, Redisson provides a series of distributed Java common objects and many distributed services.

Characteristic & Functions:

Support Redis Single Node (single) Mode, Sentinel (sentinel) Mode, Master-Slave (Master/Slave) Mode, and Cluster (Redis Cluster) Mode The program interface is called by asynchronous execution and asynchronous flow execution Data serialization, Redisson object coding class is used to serialize and deserialize the object, in order to achieve the object in Redis read and store Single collection data fragmentation. In cluster mode, Redisson provides automatic fragmentation for a single Redis collection type Provides a variety of distributed objects, such as: Object Bucket, Bitset, AtomicLong, Bloom Filter, HyperLogLog, and so on Provide rich distributed collections, such as Map, Multimap, Set, SortedSet, List, Deque, Queue, etc. Realization of distributed lock and synchronizer, reentrant lock (Reentrant Lock), fair lock (Fair Lock), interlock (MultiLock), red lock (Red Lock), semaphore (Semaphonre), expired signal lock (PermitExpirableSemaphore), etc Provides advanced distributed services such as distributed remote services (Remote Service), distributed real-time object (Live Object) services, distributed execution services (Executor Service), distributed scheduling task services (Schedule Service), and distributed mapping induction services (MapReduce) For more features and functions, please pay attention to official website: http://redisson.org

Implementation principle

redis itself does not support the above-mentioned distributed objects and collections. Redisson realizes advanced data structures and characteristics on the client side by using the characteristics of redis, such as the realization of priority queue, which is sorted by the client side and then stored in redis.

Client implementation means that when no client is online, all these data structures and features will not be preserved or automatically effective, such as the triggering of expired events or the addition of elements to the original priority queue.

Matters needing attention

Real-time

RMap has a function that can set the expiration time of key-value pairs and register event listeners for key-value pairs

Element elimination function (Eviction) The distributed RMapCache Java object of Redisson implements the elimination mechanism for a single element based on RMap. While still preserving the insertion order of elements. Because RMapCache is implemented based on RMap, it inherits both java. util. concurrent. ConcurrentMap and java. util. Map interfaces. Spring Cache integration provided by Redisson and JCache are based on this function. The current Redis itself does not support element elimination in hashing (Hash), so all expired elements are regularly cleaned through org. redisson. EvictionScheduler instances. In order to ensure the effective use of resources, each run cleans up to 300 expired elements. The start time of the task will be automatically adjusted according to the actual number of cleanups last time, and the interval will be between 1 second and 1 hour. For example, if 300 elements are deleted during this cleanup, the next cleanup will be performed after 1 second (minimum interval). 1 Once the cleaning quantity is less than the last cleaning quantity, the time interval will increase by 1.5 times.

As stated in the official wiki, this function is cleaned regularly by background threads, so this is non-real-time (issue-1234: on expired event is not executed in real-time.), and the delay is between 5 seconds and 2 hours, so scenes with high real-time requirements have to be measured by themselves.

Due to the non-real-time nature of the expiration time, the occurrence of the expiration event is also non-real-time, and the corresponding listener may be delayed for a while before receiving the notification. In my test, the error of setting ttl at the second level is relatively large, while the minute level ttl is not bad (setting value on the left side, actual time consumption on the right side):

1s _ 5s
3s _ 5s
4s _ 5s
5s _ 9s
6s _ 10s
10s _ 15s
1m _ 1m11s

Serialization

The default encoder by Redisson is JsonJacksonCodec, and JsonJackson has an infinite loop exception when serializing objects with bidirectional references. fastjson will automatically replace it with the reference $ref after checking out the bidirectional reference, ending the loop.

In my case, I serialized an service, which was hosted by spring and injected with another service. With fastjson, it can be serialized to redis normally, while JsonJackson throws an infinite loop exception.

In order to make the serialized content visible, the encoder is realized by itself without other binary encoders provided by redission:


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import org.redisson.client.codec.BaseCodec;
import org.redisson.client.protocol.Decoder;
import org.redisson.client.protocol.Encoder;​
import java.io.IOException;
​
public class FastjsonCodec extends BaseCodec {​
 private final Encoder encoder = in -> {
 ByteBuf out = ByteBufAllocator.DEFAULT.buffer();
 try {
 ByteBufOutputStream os = new ByteBufOutputStream(out);
 JSON.writeJSONString(os, in,SerializerFeature.WriteClassName);
 return os.buffer();
 } catch (IOException e) {
 out.release();
 throw e;
 } catch (Exception e) {
 out.release();
 throw new IOException(e);
 }
 };
​
 private final Decoder<Object> decoder = (buf, state) ->
 JSON.parseObject(new ByteBufInputStream(buf), Object.class);
​
 @Override
 public Decoder<Object> getValueDecoder() {
 return decoder;
 }
​
 @Override
 public Encoder getValueEncoder() {
 return encoder;
 }
}
Subscribe to Publication

The encapsulation of Redisson for subscribed publications is RTopic, which is also the implementation principle of many event listening in Redisson (for example, event listening for key-value pairs).

When you use unit tests, you find that after an event is published, subscribers need to delay 1 time before receiving the event. Specific reasons to be investigated


Related articles: