docs updated

pull/6258/head
Nikita Koksharov 3 months ago
parent 355b135627
commit 46868f2b4f

@ -1,4 +1,4 @@
# Redisson - Easy Redis Java client<br/>and Real-Time Data Platform # Redisson - Valkey & Redis Java client<br/>Complete Real-Time Data Platform
High-performance async and lock-free Java client for Redis and Valkey based on [Netty](http://netty.io) framework. High-performance async and lock-free Java client for Redis and Valkey based on [Netty](http://netty.io) framework.

@ -667,15 +667,32 @@ multimap.destroy();
_This feature is available only in [Redisson PRO](https://redisson.pro) edition._ _This feature is available only in [Redisson PRO](https://redisson.pro) edition._
Distributed Java implementation of Redis or Valkey based Key Value store for JSON objects. This object is thread-safe. Allows to store JSON value mapped by key. Operations can be executed per key or group of keys. Value is stored/retrieved using `JSON.*` commands. Both key and value are POJO objects. [RJsonStore](https://www.javadoc.io/doc/org.redisson/redisson/latest/org/redisson/api/RJsonStore.html) is a distributed Key Value store for JSON objects. Compatible with Redis or Valkey. This object is thread-safe. Allows to store JSON value mapped by key. Operations can be executed per key or group of keys. Value is stored/retrieved using `JSON.*` commands. Both key and value are POJO objects.
Allows to define `time to live` parameter per entry. Doesn't use an entry eviction task, entries are cleaned on Redis or Valkey side. Allows to define `time to live` parameter per entry. Doesn't use an entry eviction task, entries are cleaned on Redis or Valkey side.
Implements **Async**, **Reactive** and **RxJava3** interfaces. Code example of **[Async](https://www.javadoc.io/doc/org.redisson/redisson/latest/org/redisson/api/RJsonStoreAsync.html) interface** usage:
```java
RJsonStoreAsync<String, MyObject> store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
```
Code example of **[Reactive](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonStoreReactive.html) interface** usage:
```java
RedissonReactiveClient redisson = redissonClient.reactive();
RJsonStoreReactive<AnyObject> bucket = redisson.getJsonStore("anyObject", new JacksonCodec<>(AnyObject.class));
```
Code example of **[RxJava3](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonStoreRx.html) interface** usage:
```java
RedissonRxClient redisson = redissonClient.rxJava();
RJsonStoreRx<AnyObject> bucket = redisson.getJsonStore("anyObject", new JacksonCodec<>(AnyObject.class));
```
Data write code example: Data write code example:
```java ```java
RJsonStore<String, MyObject> store = redisson.getJsonStore("test", StringCodec.INSTANCE, new JacksonCodec(MyObject.class)); RJsonStore<String, MyObject> store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
MyObject t1 = new MyObject(); MyObject t1 = new MyObject();
t1.setName("name1"); t1.setName("name1");
@ -705,7 +722,7 @@ store.setIfExists("1", t1);
Data read code example: Data read code example:
```java ```java
RJsonStore<String, MyObject> store = redisson.getJsonStore("test", StringCodec.INSTANCE, new JacksonCodec(MyObject.class)); RJsonStore<String, MyObject> store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
// multiple entries at once // multiple entries at once
Map<String, MyObject> entries = store.get(Set.of("1", "2")); Map<String, MyObject> entries = store.get(Set.of("1", "2"));
@ -717,7 +734,7 @@ MyObject value2 = store.get("2");
Data deletion code example: Data deletion code example:
```java ```java
RJsonStore<String, MyObject> store = redisson.getJsonStore("test", StringCodec.INSTANCE, new JacksonCodec(MyObject.class)); RJsonStore<String, MyObject> store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
// multiple entries at once // multiple entries at once
long deleted = store.delete(Set.of("1", "2")); long deleted = store.delete(Set.of("1", "2"));
@ -727,7 +744,22 @@ boolean status = store.delete("1");
boolean status = store.delete("2"); boolean status = store.delete("2");
``` ```
For data searching index prefix should be defined in `<object_name>:` format. For example for object name "test" prefix is "test:". Keys access code examples:
```java
RJsonStore<String, MyObject> store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
// iterate keys
Set<String> keys = store.keySet();
// read all keys at once
Set<String> keys = store.readAllKeySet();
```
### Search by Object properties
For data searching, index prefix should be defined in `<object_name>:` format. For example for object name "test" prefix is "test:".
`StringCodec` should be used as object codec to enable searching by field.
Data search code example: Data search code example:
```java ```java
@ -758,17 +790,6 @@ AggregationResult ar = s.aggregate("idx", "*", AggregationOptions.defaults()
.withCursor().load("name")); .withCursor().load("name"));
``` ```
Keys access code examples:
```java
RJsonStore<String, MyObject> store = redisson.getJsonStore("test", StringCodec.INSTANCE, new JacksonCodec(MyObject.class));
// iterate keys
Set<String> keys = store.keySet();
// read all keys at once
Set<String> keys = store.readAllKeySet();
```
### Local Cache ### Local Cache
Redisson provides [JSON Store](#json-store) implementation with local cache. Redisson provides [JSON Store](#json-store) implementation with local cache.
@ -912,54 +933,6 @@ boolean status = store.delete("1");
boolean status = store.delete("2"); boolean status = store.delete("2");
``` ```
For data searching index prefix should be defined in `<object_name>:` format. For example for object name "test" prefix is "test:".
Data search code example:
```java
RSearch s = redisson.getSearch();
s.createIndex("idx", IndexOptions.defaults()
.on(IndexType.JSON)
.prefix(Arrays.asList("test:")),
FieldIndex.text("name"));
LocalCachedJsonStoreOptions ops = LocalCachedJsonStoreOptions.name("test")
.keyCodec(StringCodec.INSTANCE)
.valueCodec(new JacksonCodec<>(MyObject.class));
RLocalCachedJsonStore<String, MyObject> store = redisson.getLocalCachedJsonStore(ops);
MyObject t1 = new MyObject();
t1.setName("name1");
MyObject t2 = new MyObject();
t2.setName("name2");
Map<String, MyObject> entries = new HashMap<>();
entries.put("1", t1);
entries.put("2", t2);
store.set(entries);
// search
SearchResult r = s.search("idx", "*", QueryOptions.defaults()
.returnAttributes(new ReturnAttribute("name")));
// aggregation
AggregationResult ar = s.aggregate("idx", "*", AggregationOptions.defaults()
.withCursor().load("name"));
```
Keys access code examples:
```java
LocalCachedJsonStoreOptions ops = LocalCachedJsonStoreOptions.name("test")
.keyCodec(StringCodec.INSTANCE)
.valueCodec(new JacksonCodec<>(MyObject.class));
RLocalCachedJsonStore<String, MyObject> store = redisson.getLocalCachedJsonStore(ops);
// iterate keys
Set<String> keys = store.keySet();
// read all keys at once
Set<String> keys = store.readAllKeySet();
```
## Set ## Set
Redis or Valkey based [Set](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RSet.html) object for Java implements [Set](https://docs.oracle.com/javase/8/docs/api/java/util/Set.html) interface. This object is thread-safe. Keeps elements uniqueness via element state comparison. Set size limited to `4 294 967 295` elements. Redis or Valkey uses serialized state to check value uniqueness instead of value's `hashCode()`/`equals()` methods. Redis or Valkey based [Set](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RSet.html) object for Java implements [Set](https://docs.oracle.com/javase/8/docs/api/java/util/Set.html) interface. This object is thread-safe. Keeps elements uniqueness via element state comparison. Set size limited to `4 294 967 295` elements. Redis or Valkey uses serialized state to check value uniqueness instead of value's `hashCode()`/`equals()` methods.

@ -290,26 +290,11 @@ set.removeListener(listenerId);
## JSON object holder ## JSON object holder
Java implementation of [RJsonBucket](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonBucket.html) object stores data in JSON format using `JSON.*` commands. JSON data encoding/decoding handled by `JsonCodec` which is a required parameter. Available implementation is `org.redisson.codec.JacksonCodec` which is thread-safe. Java implementation of [RJsonBucket](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonBucket.html) object stores data in JSON format using `JSON.*` commands. JSON data encoding/decoding handled by `JsonCodec` which is a required parameter. Available implementation is `org.redisson.codec.JacksonCodec` which is thread-safe.
Use [JSON Store](collections.md/#json-store) for key-value implementation and local cache. Use [JSON Store](collections.md/#json-store) for key-value implementation and local cache support.
### Local cache
Redisson provides JSON object holder implementation with local cache.
**local cache** - so called near cache used to speed up read operations and avoid network roundtrips. It caches whole JSON object on Redisson side and executes read operations up to **45x faster** in comparison with common implementation. Local cache instances with the same name connected to the same pub/sub channel. This channel is used to exchange invalidate events between instances.
|RedissonClient<br/>method name | Local cache | Ultra-fast<br/>read/write |
| ------------- | :-----------: | :---------:|
|getJsonBucket()<br/><sub><i>open-source version</i></sub> | ❌ | ❌ |
|getJsonBucket()<br/><sub><i>[Redisson PRO](https://redisson.pro) version</i></sub> | ❌ | ✔️ |
|getLocalCachedJsonBucket()<br/><sub><i>[Redisson PRO](https://redisson.pro) version</i></sub> | ✔️ | ✔️ |
Code example: Code example:
```java ```java
RJsonBucket<AnyObject> bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class)); RJsonBucket<AnyObject> bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
// or local cached instance
RLocalCachedJsonBucket<AnyObject> bucket = redisson.getLocalCachedJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
bucket.set(new AnyObject(1)); bucket.set(new AnyObject(1));
AnyObject obj = bucket.get(); AnyObject obj = bucket.get();
@ -325,8 +310,6 @@ long aa = bucket.arrayAppend("$.obj.values", "t3", "t4");
Code example of **[Async](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonBucketAsync.html) interface** usage: Code example of **[Async](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonBucketAsync.html) interface** usage:
```java ```java
RJsonBucket<AnyObject> bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class)); RJsonBucket<AnyObject> bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
// or local cached instace
RLocalCachedJsonBucket<AnyObject> bucket = redisson.getLocalCachedJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
RFuture<Void> future = bucket.setAsync(new AnyObject(1)); RFuture<Void> future = bucket.setAsync(new AnyObject(1));
RFuture<AnyObject> objfuture = bucket.getAsync(); RFuture<AnyObject> objfuture = bucket.getAsync();
@ -343,9 +326,6 @@ Code example of **[Reactive](https://static.javadoc.io/org.redisson/redisson/lat
```java ```java
RedissonReactiveClient redisson = redissonClient.reactive(); RedissonReactiveClient redisson = redissonClient.reactive();
RJsonBucketReactive<AnyObject> bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class)); RJsonBucketReactive<AnyObject> bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
// or local cached instance
RLocalCachedJsonBucketReactive<AnyObject> bucket = redisson.getLocalCachedJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
Mono<Void> mono = bucket.set(new AnyObject(1)); Mono<Void> mono = bucket.set(new AnyObject(1));
Mono<AnyObject> objMono = bucket.get(); Mono<AnyObject> objMono = bucket.get();
@ -362,8 +342,6 @@ Code example of **[RxJava3](https://static.javadoc.io/org.redisson/redisson/late
```java ```java
RedissonRxClient redisson = redissonClient.rxJava(); RedissonRxClient redisson = redissonClient.rxJava();
RJsonBucketRx<AnyObject> bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class)); RJsonBucketRx<AnyObject> bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
// or local cached instance
RLocalCachedJsonBucketRx<AnyObject> bucket = redisson.getLocalCachedJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
Completable rx = bucket.set(new AnyObject(1)); Completable rx = bucket.set(new AnyObject(1));
Maybe<AnyObject> objRx = bucket.get(); Maybe<AnyObject> objRx = bucket.get();

@ -274,11 +274,11 @@ public class MyObject {
} }
``` ```
Please note: fields marked with `transient` keyword aren't stored in Redis. Please note: fields marked with `transient` keyword aren't stored in Redis or Valkey.
To start use it you should use one of methods below: To start use it you should use one of methods below:
`RLiveObjectService.attach()` - attaches object to Redis. Discard all the field values already in the detached instance `RLiveObjectService.attach()` - attaches object to Redis or Valkey. Discard all the field values already in the detached instance
`RLiveObjectService.merge()` - overrides current object state in Redis or Valkey with the given object state `RLiveObjectService.merge()` - overrides current object state in Redis or Valkey with the given object state
`RLiveObjectService.persist()` - stores only new object `RLiveObjectService.persist()` - stores only new object
@ -288,11 +288,11 @@ Code example:
RLiveObjectService service = redisson.getLiveObjectService(); RLiveObjectService service = redisson.getLiveObjectService();
MyLiveObject myObject = new MyLiveObject(); MyLiveObject myObject = new MyLiveObject();
myObject1.setId("1"); myObject1.setId("1");
// current state of myObject is now persisted and attached to Redis // current state of myObject is now persisted and attached to Redis or Valkey
myObject = service.persist(myObject); myObject = service.persist(myObject);
MyLiveObject myObject = new MyLiveObject("1"); MyLiveObject myObject = new MyLiveObject("1");
// current state of myObject is now cleared and attached to Redis // current state of myObject is now cleared and attached to Redis or Valkey
myObject = service.attach(myObject); myObject = service.attach(myObject);
MyLiveObject myObject = new MyLiveObject(); MyLiveObject myObject = new MyLiveObject();
@ -335,13 +335,13 @@ List.class | RedissonList.class
The conversion prefers the one nearer to the top of the table if a field type matches more than one entries. i.e. `LinkedList` implements `Deque`, `List`, `Queue`, it will be converted to a `RedissonDeque` because of this. The conversion prefers the one nearer to the top of the table if a field type matches more than one entries. i.e. `LinkedList` implements `Deque`, `List`, `Queue`, it will be converted to a `RedissonDeque` because of this.
Instances of these Redisson classes retains their states/values/entries in Redis or Valkey too, changes to them are directly reflected into Redis or Valkey without keeping values in local VM. Instances of these Redisson classes retains their states/values/entries in Redis or Valkey too, changes to them are directly reflected into database without keeping values in local VM.
### Search by Object properties ### Search by Object properties
Redisson provides comprehensive search engine for Live Object. To make a property participate in search it should be annotated with `@RIndex` annotation. Redisson provides comprehensive search engine for RLO objects. To make a property participate in search it should be annotated with `@RIndex` annotation.
!!! note "Open-source version of search engine is slow" !!! note "The open-source version of the search engine is not optimized!"
Use [Redisson PRO](https://redisson.pro) for **ultra-fast search engine**, **low JVM memory consumption during search process** and **search index partitiong in cluster**. Use [Redisson PRO](https://redisson.pro) for **ultra-fast search engine**, **low JVM memory consumption during search process** and **search index partitiong in cluster**.
Usage example: Usage example:
@ -366,14 +366,14 @@ public class MyObject {
Different type of search conditions are available: Different type of search conditions are available:
`Conditions.and` - **AND** condition for collection of nested conditions `Conditions.and()` - **AND** condition for collection of nested conditions
`Conditions.eq` - **EQUALS** condition which restricts property to defined value `Conditions.eq()` - **EQUALS** condition which restricts property to defined value
`Conditions.or` - **OR** condition for collection of nested conditions `Conditions.or()` - **OR** condition for collection of nested conditions
`Conditions.in` - **IN** condition which restricts property to set of defined values `Conditions.in()` - **IN** condition which restricts property to set of defined values
`Conditions.gt` - **GREATER THAN** condition which restricts property to defined value `Conditions.gt()` - **GREATER THAN** condition which restricts property to defined value
`Conditions.ge` - **GREATER THAN ON EQUAL** condition which restricts property to defined value `Conditions.ge()` - **GREATER THAN ON EQUAL** condition which restricts property to defined value
`Conditions.lt` - **LESS THAN** condition which restricts property to defined value `Conditions.lt()` - **LESS THAN** condition which restricts property to defined value
`Conditions.le` - **LESS THAN ON EQUAL** condition which restricts property to defined value `Conditions.le()` - **LESS THAN ON EQUAL** condition which restricts property to defined value
Once object stored in Redis or Valkey we can run search: Once object stored in Redis or Valkey we can run search:
@ -392,6 +392,73 @@ Collection<MyObject> objects = liveObjectService.find(MyObject.class,
Search index expires after `expireXXX()` method call only if the Redis or Valkey `notify-keyspace-events` setting contains the letters `Kx`. Search index expires after `expireXXX()` method call only if the Redis or Valkey `notify-keyspace-events` setting contains the letters `Kx`.
### Local Cache
_This feature is available only in [Redisson PRO](https://redisson.pro) edition._
RLO objects can be cached in local cache on the Redisson side.
**local cache** - so called near cache used to speed up read operations and avoid network roundtrips. It caches JSON Store entries on Redisson side and executes read operations up to **45x faster** in comparison with regular implementation. Local cached instances with the same name are connected to the same pub/sub channel. This channel is used for exchanging of update/invalidate events between all instances. Local cache store doesn't use `hashCode()`/`equals()` methods of key object, instead it uses hash of serialized state.
To make an RLO entity stored in local cache it should be annotated with `@RCache` annotation.
`@RCache` annotation settings:
* `storeCacheMiss` - defines whether to store a cache miss into the local cache. Default value is `false`.
* `storeMode` - defines store mode of cache data. Default value is `LOCALCACHE_REDIS`. Follow options are available:
* `LOCALCACHE` - store data in local cache only and use Redis or Valkey only for data update/invalidation.
* `LOCALCACHE_REDIS` - store data in both Redis or Valkey and local cache.
* `cacheProvider` - defines Cache provider used as local cache store. Default value is `REDISSON`. Follow options are available:
* `REDISSON` - uses Redisson own implementation
* `CAFFEINE` - uses Caffeine implementation
* `evictionPolicy` - defines local cache eviction policy. Default value is `NONE`. Follow options are available:
* `LFU` - counts how often an item was requested. Those that are used least often are discarded first.
* `LRU` - discards the least recently used items first
* `SOFT` - uses soft references, entries are removed by GC
* `WEAK` - uses weak references, entries are removed by GC
* `NONE` - no eviction
* `cacheSize` - local cache size. If cache size is `0` then local cache is unbounded. If size is `-1` then local cache is always empty and doesn't store data. Default value is `0`.
* `reconnectionStrategy` - defines strategy for load missed local cache updates after connection failure. Default value is `NONE`. Follow options are available:
* `CLEAR` - clear local cache if map instance has been disconnected for a while.
* `NONE` - no reconnection handling
* `syncStrategy` - defines local cache synchronization strategy. Default value is `INVALIDATE`. Follow options are available:
* `INVALIDATE` - Default. Invalidate cache entry across all RLocalCachedJsonStore instances on map entry change
* `UPDATE` - Insert/update cache entry across all RLocalCachedJsonStore instances on map entry change
* `NONE` - No synchronizations on map changes
* `timeToLive` - defines time to live for each entry in local cache
* `maxIdle` - defines max idle time for each entry in local cache
* `useTopicPattern` - defines whether to use a global topic pattern listener that applies to all local cache instances belonging to the same Redisson instance. Default value is `true`.
Usage example:
```java
@REntity
@RCache(cacheSize = 10, evictionPolicy = EvictionPolicy.LRU)
public class MyObject {
@RId
private String id;
private String name;
private Integer counter;
}
RLiveObjectService service = redisson.getLiveObjectService();
MyObject obj = new MyObject();
obj.setId("1");
obj.setName("Simple name");
// current state of myObject is now persisted and attached to Redis or Valkey
myObject = service.persist(obj);
// loaded from local cache
String n = myObject.getName();
```
### Advanced Usage ### Advanced Usage
As described before, RLO classes are proxy classes which can be fabricated when needed and then get cached in a `RedissonClient` instance against its original class. This process can be a bit slow and it is recommended to pre-register all the Redisson Live Object classes via `RedissonLiveObjectService` for any kind of delay-sensitive applications. The service can also be used to unregister a class if it is no longer needed. And of course it can be used to check if the class has already been registered. As described before, RLO classes are proxy classes which can be fabricated when needed and then get cached in a `RedissonClient` instance against its original class. This process can be a bit slow and it is recommended to pre-register all the Redisson Live Object classes via `RedissonLiveObjectService` for any kind of delay-sensitive applications. The service can also be used to unregister a class if it is no longer needed. And of course it can be used to check if the class has already been registered.

Loading…
Cancel
Save