or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections.mdconfiguration.mddata-structures.mdindex.mdmessaging.mdreactive-async.mdsynchronization.md

data-structures.mddocs/

0

# Specialized Data Structures

1

2

Redisson provides advanced distributed data structures beyond basic collections, including atomic operations, probabilistic structures, geospatial operations, binary data handling, and specialized utilities for various use cases.

3

4

## Capabilities

5

6

### Atomic Operations

7

8

Distributed atomic values for thread-safe numeric operations across multiple JVM instances.

9

10

```java { .api }

11

/**

12

* Get a distributed atomic long for thread-safe long operations

13

* @param name - unique name of the atomic long

14

* @return RAtomicLong instance

15

*/

16

public RAtomicLong getAtomicLong(String name);

17

public RAtomicLong getAtomicLong(CommonOptions options);

18

19

/**

20

* Get a distributed atomic double for thread-safe double operations

21

* @param name - unique name of the atomic double

22

* @return RAtomicDouble instance

23

*/

24

public RAtomicDouble getAtomicDouble(String name);

25

public RAtomicDouble getAtomicDouble(CommonOptions options);

26

27

/**

28

* Get a long adder for high-performance distributed counting

29

* @param name - unique name of the long adder

30

* @return RLongAdder instance optimized for concurrent additions

31

*/

32

public RLongAdder getLongAdder(String name);

33

public RLongAdder getLongAdder(CommonOptions options);

34

35

/**

36

* Get a double adder for high-performance distributed summing

37

* @param name - unique name of the double adder

38

* @return RDoubleAdder instance optimized for concurrent additions

39

*/

40

public RDoubleAdder getDoubleAdder(String name);

41

public RDoubleAdder getDoubleAdder(CommonOptions options);

42

```

43

44

**Atomic Interfaces:**

45

46

```java { .api }

47

// Distributed atomic long with compare-and-swap operations

48

public interface RAtomicLong extends RObject, RExpirable, RAtomicLongAsync {

49

long get();

50

void set(long newValue);

51

long getAndSet(long newValue);

52

53

// Compare and swap operations

54

boolean compareAndSet(long expect, long update);

55

boolean weakCompareAndSet(long expect, long update);

56

57

// Arithmetic operations

58

long addAndGet(long delta);

59

long getAndAdd(long delta);

60

long incrementAndGet();

61

long getAndIncrement();

62

long decrementAndGet();

63

long getAndDecrement();

64

65

// Functional operations

66

long updateAndGet(LongUnaryOperator updateFunction);

67

long getAndUpdate(LongUnaryOperator updateFunction);

68

long accumulateAndGet(long x, LongBinaryOperator accumulatorFunction);

69

long getAndAccumulate(long x, LongBinaryOperator accumulatorFunction);

70

}

71

72

// Distributed atomic double

73

public interface RAtomicDouble extends RObject, RExpirable, RAtomicDoubleAsync {

74

double get();

75

void set(double newValue);

76

double getAndSet(double newValue);

77

78

boolean compareAndSet(double expect, double update);

79

double addAndGet(double delta);

80

double getAndAdd(double delta);

81

82

// Functional operations

83

double updateAndGet(DoubleUnaryOperator updateFunction);

84

double getAndUpdate(DoubleUnaryOperator updateFunction);

85

double accumulateAndGet(double x, DoubleBinaryOperator accumulatorFunction);

86

double getAndAccumulate(double x, DoubleBinaryOperator accumulatorFunction);

87

}

88

89

// High-performance distributed counter

90

public interface RLongAdder extends RObject, RExpirable, RLongAdderAsync {

91

void add(long x);

92

void increment();

93

void decrement();

94

long sum();

95

void reset();

96

long sumThenReset();

97

String toString();

98

}

99

100

// High-performance distributed double accumulator

101

public interface RDoubleAdder extends RObject, RExpirable, RDoubleAdderAsync {

102

void add(double x);

103

double sum();

104

void reset();

105

double sumThenReset();

106

String toString();

107

}

108

```

109

110

**Usage Examples:**

111

112

```java

113

// Atomic long operations

114

RAtomicLong counter = redisson.getAtomicLong("globalCounter");

115

counter.set(100);

116

117

// Thread-safe operations across multiple JVMs

118

long newValue = counter.incrementAndGet(); // 101

119

long previous = counter.getAndAdd(10); // returns 101, sets to 111

120

121

// Compare and swap for conditional updates

122

long current = counter.get();

123

boolean success = counter.compareAndSet(current, current * 2);

124

if (success) {

125

System.out.println("Successfully doubled the counter");

126

}

127

128

// Functional updates

129

counter.updateAndGet(value -> value > 200 ? 0 : value + 1);

130

counter.accumulateAndGet(5, (current, delta) -> Math.max(current, delta));

131

132

// High-performance counting with RLongAdder

133

RLongAdder adder = redisson.getLongAdder("requestCounter");

134

135

// Multiple threads can increment concurrently with high performance

136

adder.increment();

137

adder.add(5);

138

139

// Get sum when needed (more expensive operation)

140

long totalRequests = adder.sum();

141

System.out.println("Total requests: " + totalRequests);

142

143

// Reset counter

144

long finalCount = adder.sumThenReset(); // Get value and reset atomically

145

146

// Atomic double for precise calculations

147

RAtomicDouble balance = redisson.getAtomicDouble("accountBalance");

148

balance.set(1000.50);

149

150

double newBalance = balance.addAndGet(-50.25); // Withdraw $50.25

151

boolean withdrawSuccess = balance.compareAndSet(950.25, 900.25); // Conditional withdraw

152

```

153

154

### Probabilistic Data Structures

155

156

Memory-efficient probabilistic data structures for approximate operations on large datasets.

157

158

```java { .api }

159

/**

160

* Get a Bloom filter for membership testing

161

* @param name - unique name of the Bloom filter

162

* @return RBloomFilter instance for approximate membership testing

163

*/

164

public <V> RBloomFilter<V> getBloomFilter(String name);

165

public <V> RBloomFilter<V> getBloomFilter(String name, Codec codec);

166

public <V> RBloomFilter<V> getBloomFilter(PlainOptions options);

167

168

/**

169

* Get a HyperLogLog for cardinality estimation

170

* @param name - unique name of the HyperLogLog

171

* @return RHyperLogLog instance for approximate unique count

172

*/

173

public <V> RHyperLogLog<V> getHyperLogLog(String name);

174

public <V> RHyperLogLog<V> getHyperLogLog(String name, Codec codec);

175

public <V> RHyperLogLog<V> getHyperLogLog(PlainOptions options);

176

```

177

178

**Probabilistic Interfaces:**

179

180

```java { .api }

181

// Bloom filter for membership testing

182

public interface RBloomFilter<T> extends RObject, RExpirable, RBloomFilterAsync<T> {

183

// Filter initialization

184

boolean tryInit(long expectedInsertions, double falseProbability);

185

boolean isExists();

186

187

// Membership operations

188

boolean contains(T object);

189

boolean add(T object);

190

191

// Bulk operations

192

boolean[] contains(T... objects);

193

boolean addAll(Collection<T> c);

194

boolean containsAll(Collection<T> c);

195

196

// Filter statistics

197

long count();

198

long getExpectedInsertions();

199

double getFalseProbability();

200

long getHashIterations();

201

long getSize();

202

}

203

204

// HyperLogLog for cardinality estimation

205

public interface RHyperLogLog<V> extends RObject, RExpirable, RHyperLogLogAsync<V> {

206

// Add elements for counting unique values

207

boolean add(V obj);

208

boolean addAll(Collection<V> objects);

209

210

// Get approximate unique count

211

long count();

212

213

// Merge with other HyperLogLogs

214

long countWith(String... otherLogNames);

215

void mergeWith(String... otherLogNames);

216

}

217

```

218

219

**Usage Examples:**

220

221

```java

222

// Bloom filter for membership testing

223

RBloomFilter<String> bloomFilter = redisson.getBloomFilter("uniqueUsers");

224

225

// Initialize filter with expected elements and false positive rate

226

bloomFilter.tryInit(10000, 0.03); // 10K elements, 3% false positive rate

227

228

// Add elements

229

bloomFilter.add("user123");

230

bloomFilter.add("user456");

231

bloomFilter.add("user789");

232

233

// Test membership

234

boolean containsUser = bloomFilter.contains("user123"); // true

235

boolean containsNew = bloomFilter.contains("user999"); // false (or small chance of false positive)

236

237

// Bulk operations

238

Collection<String> users = Arrays.asList("user1", "user2", "user3");

239

bloomFilter.addAll(users);

240

boolean allExist = bloomFilter.containsAll(users); // true

241

242

// Check filter statistics

243

long elementCount = bloomFilter.count();

244

double falsePositiveRate = bloomFilter.getFalseProbability();

245

System.out.println("Filter contains ~" + elementCount + " elements with " +

246

(falsePositiveRate * 100) + "% false positive rate");

247

248

// HyperLogLog for unique count estimation

249

RHyperLogLog<String> uniqueVisitors = redisson.getHyperLogLog("dailyVisitors");

250

251

// Add visitor IDs (can be millions with constant memory usage)

252

uniqueVisitors.add("visitor1");

253

uniqueVisitors.add("visitor2");

254

uniqueVisitors.add("visitor1"); // Duplicate - won't affect count

255

256

// Add many visitors

257

for (int i = 0; i < 100000; i++) {

258

uniqueVisitors.add("visitor" + i);

259

}

260

261

// Get approximate unique count (very memory efficient)

262

long uniqueCount = uniqueVisitors.count();

263

System.out.println("Approximate unique visitors: " + uniqueCount);

264

265

// Merge multiple HyperLogLogs

266

RHyperLogLog<String> weeklyVisitors = redisson.getHyperLogLog("weeklyVisitors");

267

RHyperLogLog<String> monthlyVisitors = redisson.getHyperLogLog("monthlyVisitors");

268

269

// Count across multiple logs without merging

270

long totalUniqueVisitors = uniqueVisitors.countWith("weeklyVisitors", "monthlyVisitors");

271

272

// Merge logs into one

273

uniqueVisitors.mergeWith("weeklyVisitors", "monthlyVisitors");

274

```

275

276

### Geospatial Operations

277

278

Geospatial data structures for location-based operations using Redis GEO commands.

279

280

```java { .api }

281

/**

282

* Get a geo-spatial collection for location operations

283

* @param name - unique name of the geo collection

284

* @return RGeo instance for geospatial operations

285

*/

286

public <V> RGeo<V> getGeo(String name);

287

public <V> RGeo<V> getGeo(String name, Codec codec);

288

public <V> RGeo<V> getGeo(PlainOptions options);

289

```

290

291

**Geo Interface:**

292

293

```java { .api }

294

// Geospatial operations interface

295

public interface RGeo<V> extends RObject, RExpirable, RGeoAsync<V> {

296

// Add locations

297

long add(double longitude, double latitude, V member);

298

long add(GeoEntry... entries);

299

300

// Distance calculations

301

Double dist(V firstMember, V secondMember, GeoUnit geoUnit);

302

303

// Get coordinates

304

Map<V, GeoPosition> pos(V... members);

305

List<String> hash(V... members);

306

307

// Radius searches

308

List<V> radius(double longitude, double latitude, double radius, GeoUnit geoUnit);

309

List<V> radius(double longitude, double latitude, double radius, GeoUnit geoUnit, int count);

310

List<V> radius(double longitude, double latitude, double radius, GeoUnit geoUnit,

311

GeoOrder geoOrder);

312

List<V> radius(double longitude, double latitude, double radius, GeoUnit geoUnit,

313

GeoOrder geoOrder, int count);

314

315

// Radius searches with distance

316

Map<V, Double> radiusWithDistance(double longitude, double latitude, double radius,

317

GeoUnit geoUnit);

318

Map<V, Double> radiusWithDistance(double longitude, double latitude, double radius,

319

GeoUnit geoUnit, int count);

320

Map<V, Double> radiusWithDistance(double longitude, double latitude, double radius,

321

GeoUnit geoUnit, GeoOrder geoOrder);

322

323

// Radius searches with position

324

Map<V, GeoPosition> radiusWithPosition(double longitude, double latitude, double radius,

325

GeoUnit geoUnit);

326

327

// Member-based radius searches

328

List<V> radius(V member, double radius, GeoUnit geoUnit);

329

Map<V, Double> radiusWithDistance(V member, double radius, GeoUnit geoUnit);

330

Map<V, GeoPosition> radiusWithPosition(V member, double radius, GeoUnit geoUnit);

331

332

// Search and store results

333

long radiusStoreTo(String destName, double longitude, double latitude, double radius,

334

GeoUnit geoUnit);

335

long radiusStoreTo(String destName, V member, double radius, GeoUnit geoUnit);

336

}

337

338

// Geospatial data types

339

public class GeoEntry {

340

private final double longitude;

341

private final double latitude;

342

private final Object member;

343

344

public GeoEntry(double longitude, double latitude, Object member);

345

// getters...

346

}

347

348

public class GeoPosition {

349

private final double longitude;

350

private final double latitude;

351

352

public GeoPosition(double longitude, double latitude);

353

// getters...

354

}

355

356

public enum GeoUnit {

357

METERS("m"),

358

KILOMETERS("km"),

359

MILES("mi"),

360

FEET("ft");

361

362

private final String value;

363

GeoUnit(String value) { this.value = value; }

364

}

365

366

public enum GeoOrder {

367

ASC, DESC

368

}

369

```

370

371

**Usage Examples:**

372

373

```java

374

// Geospatial operations for location services

375

RGeo<String> locations = redisson.getGeo("cityLocations");

376

377

// Add locations (longitude, latitude, member)

378

locations.add(-74.0059, 40.7128, "New York"); // NYC

379

locations.add(-118.2437, 34.0522, "Los Angeles"); // LA

380

locations.add(-87.6298, 41.8781, "Chicago"); // Chicago

381

locations.add(-122.4194, 37.7749, "San Francisco"); // SF

382

383

// Calculate distance between cities

384

Double distance = locations.dist("New York", "Los Angeles", GeoUnit.MILES);

385

System.out.println("Distance NY to LA: " + distance + " miles");

386

387

// Get coordinates of a city

388

Map<String, GeoPosition> positions = locations.pos("New York", "Chicago");

389

GeoPosition nycPos = positions.get("New York");

390

System.out.println("NYC: " + nycPos.getLongitude() + ", " + nycPos.getLatitude());

391

392

// Find cities within radius of a point (around NYC)

393

List<String> nearbyCities = locations.radius(-74.0059, 40.7128, 300, GeoUnit.MILES);

394

System.out.println("Cities within 300 miles of NYC: " + nearbyCities);

395

396

// Find cities with distances

397

Map<String, Double> citiesWithDistance = locations.radiusWithDistance(-74.0059, 40.7128,

398

500, GeoUnit.MILES);

399

citiesWithDistance.forEach((city, dist) -> {

400

System.out.println(city + " is " + dist + " miles away");

401

});

402

403

// Find cities near another city

404

List<String> nearChicago = locations.radius("Chicago", 200, GeoUnit.MILES);

405

System.out.println("Cities within 200 miles of Chicago: " + nearChicago);

406

407

// Store search results in another geo collection

408

long stored = locations.radiusStoreTo("eastCoastCities", -74.0059, 40.7128,

409

300, GeoUnit.MILES);

410

System.out.println("Stored " + stored + " east coast cities");

411

412

// Delivery service example

413

RGeo<String> deliveryPoints = redisson.getGeo("deliveryLocations");

414

415

// Add delivery addresses

416

deliveryPoints.add(-73.935242, 40.730610, "customer1"); // East Village

417

deliveryPoints.add(-73.989308, 40.756800, "customer2"); // Times Square

418

deliveryPoints.add(-73.958805, 40.768923, "customer3"); // Upper East Side

419

420

// Find deliveries within 2 miles of delivery truck location

421

List<String> nearbyDeliveries = deliveryPoints.radius(-73.950000, 40.750000,

422

2, GeoUnit.MILES);

423

System.out.println("Nearby deliveries: " + nearbyDeliveries);

424

425

// Restaurant finder example

426

RGeo<Restaurant> restaurants = redisson.getGeo("restaurants");

427

restaurants.add(-73.9857, 40.7484, new Restaurant("Pizza Palace", "Italian"));

428

restaurants.add(-73.9759, 40.7505, new Restaurant("Burger Barn", "American"));

429

restaurants.add(-73.9851, 40.7589, new Restaurant("Sushi Spot", "Japanese"));

430

431

// Find restaurants near user location, sorted by distance

432

Map<Restaurant, Double> nearbyRestaurants = restaurants.radiusWithDistance(

433

-73.9800, 40.7500, 0.5, GeoUnit.MILES, GeoOrder.ASC);

434

435

nearbyRestaurants.forEach((restaurant, distance) -> {

436

System.out.println(restaurant.getName() + " - " + distance + " miles");

437

});

438

```

439

440

### Binary Data Operations

441

442

Binary data handling with bit-level operations and binary streams.

443

444

```java { .api }

445

/**

446

* Get a distributed bit set for binary operations

447

* @param name - unique name of the bit set

448

* @return RBitSet instance for bit manipulation

449

*/

450

public RBitSet getBitSet(String name);

451

public RBitSet getBitSet(CommonOptions options);

452

453

/**

454

* Get a binary stream for raw binary data operations

455

* @param name - unique name of the binary stream

456

* @return RBinaryStream instance for binary I/O

457

*/

458

public RBinaryStream getBinaryStream(String name);

459

public RBinaryStream getBinaryStream(CommonOptions options);

460

```

461

462

**Binary Interfaces:**

463

464

```java { .api }

465

// Distributed bit set for binary operations

466

public interface RBitSet extends RObject, RExpirable, RBitSetAsync {

467

// Bit operations

468

boolean get(long bitIndex);

469

boolean getAndSet(long bitIndex);

470

void set(long bitIndex);

471

void set(long bitIndex, boolean value);

472

void set(long fromIndex, long toIndex);

473

void set(long fromIndex, long toIndex, boolean value);

474

475

// Bit clearing

476

void clear();

477

void clear(long bitIndex);

478

void clear(long fromIndex, long toIndex);

479

480

// Bit testing

481

boolean isEmpty();

482

long length();

483

long size();

484

long cardinality(); // Count of set bits

485

486

// Bit operations with other bit sets

487

void and(String... bitSetNames);

488

void or(String... bitSetNames);

489

void xor(String... bitSetNames);

490

void not();

491

492

// Bit searching

493

long nextSetBit(long fromIndex);

494

long nextClearBit(long fromIndex);

495

long previousSetBit(long fromIndex);

496

long previousClearBit(long fromIndex);

497

498

// Bulk operations

499

byte[] toByteArray();

500

BitSet asBitSet();

501

}

502

503

// Binary stream for raw data

504

public interface RBinaryStream extends RObject, RBinaryStreamAsync {

505

// Stream operations

506

InputStream getInputStream();

507

OutputStream getOutputStream();

508

509

// Direct read/write

510

void set(byte[] value);

511

void set(InputStream inputStream);

512

byte[] get();

513

514

// Partial operations

515

byte[] get(long offset, long length);

516

void set(byte[] value, long offset);

517

518

// Stream information

519

long size();

520

boolean delete();

521

}

522

```

523

524

**Usage Examples:**

525

526

```java

527

// Bit set operations for flags and permissions

528

RBitSet permissions = redisson.getBitSet("userPermissions");

529

530

// Set permission bits (bit index represents permission ID)

531

permissions.set(0); // Read permission

532

permissions.set(1); // Write permission

533

permissions.set(5); // Admin permission

534

535

// Check permissions

536

boolean canRead = permissions.get(0); // true

537

boolean canWrite = permissions.get(1); // true

538

boolean canDelete = permissions.get(2); // false

539

540

// Set multiple bits

541

permissions.set(10, 15); // Set bits 10-14

542

543

// Count set permissions

544

long activePermissions = permissions.cardinality();

545

System.out.println("User has " + activePermissions + " permissions");

546

547

// Combine permissions from multiple users

548

RBitSet user1Perms = redisson.getBitSet("user1Permissions");

549

RBitSet user2Perms = redisson.getBitSet("user2Permissions");

550

551

user1Perms.set(0, 5); // Basic permissions

552

user2Perms.set(3, 8); // Different permissions

553

554

// Create combined permission set

555

RBitSet combinedPerms = redisson.getBitSet("combinedPermissions");

556

combinedPerms.or("user1Permissions", "user2Permissions");

557

558

// Find next available permission slot

559

long nextAvailable = combinedPerms.nextClearBit(0);

560

System.out.println("Next available permission ID: " + nextAvailable);

561

562

// Binary stream for file-like operations

563

RBinaryStream fileData = redisson.getBinaryStream("uploadedFile");

564

565

// Store binary data

566

byte[] imageData = loadImageFromDisk();

567

fileData.set(imageData);

568

569

// Read binary data

570

byte[] retrievedData = fileData.get();

571

saveImageToDisk(retrievedData);

572

573

// Stream operations for large files

574

try (InputStream input = new FileInputStream("largefile.zip");

575

OutputStream output = fileData.getOutputStream()) {

576

577

byte[] buffer = new byte[8192];

578

int bytesRead;

579

while ((bytesRead = input.read(buffer)) != -1) {

580

output.write(buffer, 0, bytesRead);

581

}

582

}

583

584

// Read part of binary data

585

long fileSize = fileData.size();

586

byte[] header = fileData.get(0, 1024); // First 1KB

587

byte[] footer = fileData.get(fileSize - 1024, 1024); // Last 1KB

588

589

// Update part of binary data

590

byte[] newHeader = createNewHeader();

591

fileData.set(newHeader, 0); // Replace header

592

593

System.out.println("File size: " + fileData.size() + " bytes");

594

```

595

596

### ID Generation

597

598

Distributed ID generation for unique identifier creation across multiple instances.

599

600

```java { .api }

601

/**

602

* Get an ID generator for distributed unique ID creation

603

* @param name - unique name of the ID generator

604

* @return RIdGenerator instance

605

*/

606

public RIdGenerator getIdGenerator(String name);

607

public RIdGenerator getIdGenerator(CommonOptions options);

608

```

609

610

**ID Generator Interface:**

611

612

```java { .api }

613

public interface RIdGenerator extends RObject, RExpirable, RIdGeneratorAsync {

614

// Initialize generator with allocation size

615

boolean tryInit(long value, long allocationSize);

616

617

// Generate next ID

618

long nextId();

619

620

// Current state

621

long current();

622

623

// Allocation settings

624

long getAllocationSize();

625

boolean expire(long timeToLive, TimeUnit timeUnit);

626

}

627

```

628

629

**Usage Examples:**

630

631

```java

632

// Distributed ID generation

633

RIdGenerator orderIds = redisson.getIdGenerator("orderIdGenerator");

634

635

// Initialize with starting value and allocation size

636

orderIds.tryInit(10000, 100); // Start at 10000, allocate 100 IDs at a time

637

638

// Generate unique order IDs

639

long orderId1 = orderIds.nextId(); // 10000

640

long orderId2 = orderIds.nextId(); // 10001

641

long orderId3 = orderIds.nextId(); // 10002

642

643

System.out.println("Generated order IDs: " + orderId1 + ", " + orderId2 + ", " + orderId3);

644

645

// Multiple ID generators for different entity types

646

RIdGenerator userIds = redisson.getIdGenerator("userIdGenerator");

647

RIdGenerator productIds = redisson.getIdGenerator("productIdGenerator");

648

649

userIds.tryInit(1000, 50);

650

productIds.tryInit(5000, 25);

651

652

// Each generator maintains independent sequences

653

long userId = userIds.nextId(); // 1000

654

long productId = productIds.nextId(); // 5000

655

656

// Check current values

657

long currentUser = userIds.current();

658

long currentProduct = productIds.current();

659

660

System.out.println("Current user ID: " + currentUser);

661

System.out.println("Current product ID: " + currentProduct);

662

663

// High-performance ID generation in multi-threaded environment

664

ExecutorService executor = Executors.newFixedThreadPool(10);

665

RIdGenerator threadSafeIds = redisson.getIdGenerator("threadSafeGenerator");

666

threadSafeIds.tryInit(0, 1000); // Large allocation for high throughput

667

668

// Multiple threads generating IDs concurrently

669

for (int i = 0; i < 10; i++) {

670

executor.submit(() -> {

671

for (int j = 0; j < 1000; j++) {

672

long id = threadSafeIds.nextId();

673

System.out.println("Thread " + Thread.currentThread().getName() +

674

" generated ID: " + id);

675

}

676

});

677

}

678

679

executor.shutdown();

680

```

681

682

### Rate Limiting

683

684

Distributed rate limiting for controlling request rates across multiple instances.

685

686

```java { .api }

687

/**

688

* Get a rate limiter for distributed rate limiting

689

* @param name - unique name of the rate limiter

690

* @return RRateLimiter instance

691

*/

692

public RRateLimiter getRateLimiter(String name);

693

public RRateLimiter getRateLimiter(CommonOptions options);

694

```

695

696

**Rate Limiter Interface:**

697

698

```java { .api }

699

public interface RRateLimiter extends RObject, RExpirable, RRateLimiterAsync {

700

// Initialize rate limiter

701

boolean trySetRate(RateType type, long rate, long rateInterval, RateIntervalUnit rateIntervalUnit);

702

703

// Acquire permits

704

boolean tryAcquire();

705

boolean tryAcquire(long permits);

706

boolean tryAcquire(long timeout, TimeUnit unit);

707

boolean tryAcquire(long permits, long timeout, TimeUnit unit);

708

709

void acquire();

710

void acquire(long permits);

711

712

// Rate limiter information

713

long availablePermits();

714

RateLimiterConfig getConfig();

715

}

716

717

public enum RateType {

718

OVERALL, // Total rate across all instances

719

PER_CLIENT // Rate per client instance

720

}

721

722

public enum RateIntervalUnit {

723

SECONDS, MINUTES, HOURS, DAYS

724

}

725

```

726

727

**Usage Examples:**

728

729

```java

730

// API rate limiting

731

RRateLimiter apiLimiter = redisson.getRateLimiter("apiRequests");

732

733

// Allow 100 requests per minute across all instances

734

apiLimiter.trySetRate(RateType.OVERALL, 100, 1, RateIntervalUnit.MINUTES);

735

736

// Check if request is allowed

737

if (apiLimiter.tryAcquire()) {

738

// Process API request

739

processApiRequest();

740

} else {

741

// Rate limit exceeded

742

throw new RateLimitExceededException("Too many requests");

743

}

744

745

// Per-user rate limiting

746

RRateLimiter userLimiter = redisson.getRateLimiter("user:" + userId + ":requests");

747

userLimiter.trySetRate(RateType.PER_CLIENT, 10, 1, RateIntervalUnit.MINUTES);

748

749

// Acquire multiple permits for batch operations

750

if (userLimiter.tryAcquire(5, 1, TimeUnit.SECONDS)) {

751

processBatchRequest(5);

752

}

753

754

// Blocking acquire with automatic rate limiting

755

userLimiter.acquire(); // Blocks until permit is available

756

processRequest();

757

```

758

759

### Time Series Data

760

761

Time series data structures for storing and querying time-ordered data (Redis 5.0.0+).

762

763

```java { .api }

764

/**

765

* Get a time series for time-ordered data storage

766

* @param name - unique name of the time series

767

* @return RTimeSeries instance

768

*/

769

public <V, L> RTimeSeries<V, L> getTimeSeries(String name);

770

public <V, L> RTimeSeries<V, L> getTimeSeries(String name, Codec codec);

771

public <V, L> RTimeSeries<V, L> getTimeSeries(PlainOptions options);

772

```

773

774

**Time Series Interface:**

775

776

```java { .api }

777

public interface RTimeSeries<V, L> extends RObject, RExpirable, RTimeSeriesAsync<V, L> {

778

// Add data points

779

void add(long timestamp, V object);

780

void add(long timestamp, V object, L label);

781

void addAll(Map<Long, V> objects);

782

783

// Range queries

784

Collection<TimeSeriesEntry<V, L>> range(long startTimestamp, long endTimestamp);

785

Collection<TimeSeriesEntry<V, L>> range(long startTimestamp, long endTimestamp, int count);

786

Collection<TimeSeriesEntry<V, L>> rangeReversed(long startTimestamp, long endTimestamp);

787

788

// Get entries by count

789

Collection<TimeSeriesEntry<V, L>> first(int count);

790

Collection<TimeSeriesEntry<V, L>> last(int count);

791

792

// Size and info

793

long size();

794

long size(long startTimestamp, long endTimestamp);

795

TimeSeriesEntry<V, L> firstEntry();

796

TimeSeriesEntry<V, L> lastEntry();

797

798

// Remove operations

799

boolean remove(long timestamp);

800

long removeRange(long startTimestamp, long endTimestamp);

801

802

// Polling operations

803

Collection<TimeSeriesEntry<V, L>> pollFirst(int count);

804

Collection<TimeSeriesEntry<V, L>> pollLast(int count);

805

}

806

807

public class TimeSeriesEntry<V, L> {

808

private final long timestamp;

809

private final V value;

810

private final L label;

811

812

// constructors and getters...

813

}

814

```

815

816

**Usage Examples:**

817

818

```java

819

// System metrics time series

820

RTimeSeries<Double, String> cpuMetrics = redisson.getTimeSeries("cpu_usage");

821

822

// Add CPU usage data points

823

long now = System.currentTimeMillis();

824

cpuMetrics.add(now, 45.5, "server1");

825

cpuMetrics.add(now + 60000, 52.3, "server1"); // 1 minute later

826

cpuMetrics.add(now + 120000, 38.7, "server1"); // 2 minutes later

827

828

// Query metrics for the last hour

829

long oneHourAgo = now - (60 * 60 * 1000);

830

Collection<TimeSeriesEntry<Double, String>> recentMetrics =

831

cpuMetrics.range(oneHourAgo, now);

832

833

recentMetrics.forEach(entry -> {

834

System.out.println("Time: " + entry.getTimestamp() +

835

", CPU: " + entry.getValue() + "%" +

836

", Server: " + entry.getLabel());

837

});

838

839

// Stock price time series

840

RTimeSeries<BigDecimal, String> stockPrices = redisson.getTimeSeries("AAPL_prices");

841

842

// Add stock price data

843

stockPrices.add(now, new BigDecimal("150.25"), "NASDAQ");

844

stockPrices.add(now + 300000, new BigDecimal("151.10"), "NASDAQ"); // 5 minutes later

845

846

// Get latest 10 price points

847

Collection<TimeSeriesEntry<BigDecimal, String>> latestPrices = stockPrices.last(10);

848

849

// Remove old data (older than 30 days)

850

long thirtyDaysAgo = now - (30L * 24 * 60 * 60 * 1000);

851

long removedCount = stockPrices.removeRange(0, thirtyDaysAgo);

852

System.out.println("Removed " + removedCount + " old entries");

853

```

854

855

### Streams

856

857

Redis Streams for message streaming and event sourcing (Redis 5.0.0+).

858

859

```java { .api }

860

/**

861

* Get a Redis stream for message streaming

862

* @param name - unique name of the stream

863

* @return RStream instance

864

*/

865

public <K, V> RStream<K, V> getStream(String name);

866

public <K, V> RStream<K, V> getStream(String name, Codec codec);

867

public <K, V> RStream<K, V> getStream(PlainOptions options);

868

```

869

870

**Stream Interface:**

871

872

```java { .api }

873

public interface RStream<K, V> extends RObject, RExpirable, RStreamAsync<K, V> {

874

// Add messages

875

StreamMessageId add(StreamAddArgs<K, V> args);

876

StreamMessageId add(K key, V value);

877

StreamMessageId add(Map<K, V> entries);

878

879

// Read messages

880

Map<String, Map<StreamMessageId, Map<K, V>>> read(StreamReadArgs args);

881

Map<StreamMessageId, Map<K, V>> read(StreamMessageId id);

882

Map<StreamMessageId, Map<K, V>> read(int count, StreamMessageId id);

883

884

// Range operations

885

Map<StreamMessageId, Map<K, V>> range(StreamMessageId startId, StreamMessageId endId);

886

Map<StreamMessageId, Map<K, V>> range(int count, StreamMessageId startId, StreamMessageId endId);

887

Map<StreamMessageId, Map<K, V>> rangeReversed(StreamMessageId startId, StreamMessageId endId);

888

889

// Consumer groups

890

void createGroup(String groupName);

891

void createGroup(String groupName, StreamMessageId id);

892

893

// Stream info

894

long size();

895

StreamInfo<K, V> getInfo();

896

897

// Remove operations

898

long remove(StreamMessageId... ids);

899

long trim(StreamTrimArgs args);

900

}

901

902

public class StreamMessageId {

903

public static final StreamMessageId NEWEST = new StreamMessageId("$");

904

public static final StreamMessageId ALL = new StreamMessageId("0");

905

906

// constructors and methods...

907

}

908

```

909

910

**Usage Examples:**

911

912

```java

913

// Event streaming

914

RStream<String, Object> eventStream = redisson.getStream("user_events");

915

916

// Add events to stream

917

Map<String, Object> userLogin = new HashMap<>();

918

userLogin.put("event", "login");

919

userLogin.put("userId", "user123");

920

userLogin.put("timestamp", System.currentTimeMillis());

921

userLogin.put("ip", "192.168.1.100");

922

923

StreamMessageId loginId = eventStream.add(userLogin);

924

System.out.println("Added login event with ID: " + loginId);

925

926

// Add purchase event

927

StreamMessageId purchaseId = eventStream.add("event", "purchase",

928

"userId", "user123",

929

"productId", "prod456",

930

"amount", 99.99);

931

932

// Read all messages from beginning

933

Map<StreamMessageId, Map<String, Object>> allEvents =

934

eventStream.read(StreamMessageId.ALL);

935

936

allEvents.forEach((id, event) -> {

937

System.out.println("Event ID: " + id + ", Data: " + event);

938

});

939

940

// Create consumer group for processing

941

eventStream.createGroup("analytics_processor");

942

943

// Chat messaging with streams

944

RStream<String, String> chatStream = redisson.getStream("chat:room1");

945

946

// Send messages

947

chatStream.add("user", "alice", "message", "Hello everyone!");

948

chatStream.add("user", "bob", "message", "Hi Alice!");

949

chatStream.add("user", "charlie", "message", "Good morning!");

950

951

// Read latest messages

952

Map<StreamMessageId, Map<String, String>> recentMessages =

953

chatStream.read(10, StreamMessageId.NEWEST);

954

955

// Process messages

956

recentMessages.forEach((id, msg) -> {

957

String user = msg.get("user");

958

String message = msg.get("message");

959

System.out.println("[" + user + "]: " + message);

960

});

961

962

// Log processing with streams

963

RStream<String, Object> logStream = redisson.getStream("application_logs");

964

965

// Add log entries

966

logStream.add("level", "ERROR",

967

"message", "Database connection failed",

968

"component", "UserService",

969

"timestamp", System.currentTimeMillis());

970

971

logStream.add("level", "INFO",

972

"message", "User registered successfully",

973

"userId", "user789",

974

"timestamp", System.currentTimeMillis());

975

976

// Create consumer group for log processing

977

logStream.createGroup("log_processor");

978

979

// Trim old logs (keep last 1000 entries)

980

long trimmed = logStream.trim(StreamTrimArgs.maxLen(1000));

981

System.out.println("Trimmed " + trimmed + " old log entries");

982

```

983

984

## Advanced Data Structure Patterns

985

986

```java { .api }

987

// Combining data structures for complex operations

988

public class AdvancedPatterns {

989

990

// Rate limiting with atomic operations

991

public static boolean isRequestAllowed(RedissonClient redisson, String clientId,

992

int maxRequests, int windowSeconds) {

993

RAtomicLong requestCount = redisson.getAtomicLong("rate_limit:" + clientId);

994

995

long current = requestCount.get();

996

if (current == 0) {

997

// First request, set expiration

998

requestCount.set(1);

999

requestCount.expire(windowSeconds, TimeUnit.SECONDS);

1000

return true;

1001

} else if (current < maxRequests) {

1002

requestCount.incrementAndGet();

1003

return true;

1004

} else {

1005

return false; // Rate limit exceeded

1006

}

1007

}

1008

1009

// Caching with Bloom filter pre-check

1010

public static <T> T getWithBloomFilter(RedissonClient redisson, String key,

1011

Class<T> type, Supplier<T> loader) {

1012

RBloomFilter<String> cacheFilter = redisson.getBloomFilter("cache_filter");

1013

1014

// Quick check if key might exist

1015

if (!cacheFilter.contains(key)) {

1016

return null; // Definitely not in cache

1017

}

1018

1019

// Might exist, check actual cache

1020

RBucket<T> bucket = redisson.getBucket(key);

1021

T value = bucket.get();

1022

1023

if (value == null && loader != null) {

1024

// Load and cache

1025

value = loader.get();

1026

if (value != null) {

1027

bucket.set(value);

1028

cacheFilter.add(key);

1029

}

1030

}

1031

1032

return value;

1033

}

1034

1035

// Geospatial + time-series for location tracking

1036

public static void trackLocation(RedissonClient redisson, String userId,

1037

double longitude, double latitude) {

1038

// Store in geospatial index

1039

RGeo<String> locations = redisson.getGeo("user_locations");

1040

locations.add(longitude, latitude, userId);

1041

1042

// Store in time series for history

1043

RTimeSeries<GeoPosition, String> locationHistory =

1044

redisson.getTimeSeries("location_history:" + userId);

1045

locationHistory.add(System.currentTimeMillis(), new GeoPosition(longitude, latitude));

1046

1047

// Update atomic counter

1048

RAtomicLong locationUpdates = redisson.getAtomicLong("location_updates:" + userId);

1049

locationUpdates.incrementAndGet();

1050

}

1051

}

1052

```