作为 Java 开发人员,我们若想在程序中集成 Redis,必须使用 Redis 的第三方库。而 Redisson 就是用于在 Java 程序中操作 Redis 的库,它使得我们可以在程序中轻松地使用 Redis。Redisson 在 java.util 中常用接口的基础上,为我们提供了一系列具有分布式特性的工具类。
安装 Redisson 最便捷的方法是使用 Maven 或者 Gradle:
•Maven
<dependency>
<groupId>org.redissongroupId>
<artifactId>redissonartifactId>
<version>3.11.4version>
dependency>
•Gradle
compile group: 'org.redisson', name: 'redisson', version: '3.11.4'
目前 Redisson 最新版是 3.11.4,当然你也可以通过搜索 Maven 中央仓库 mvnrepository[1] 来找到 Redisson 的各种版本。
安装 Redisson 后,只需使用 Java 编译器即可编译和运行 Redisson 代码:
javac RedissonExamples.java
java RedissonExamples
RedissonClient 是一个在 Java 中实现的 in-memory 数据库 Redis 的客户端。它提供了很多高级功能,如分布式对象、分布式锁、分布式集合等。
在 RedissonClient 中,RList
是用于表示 Redis 中的列表数据结构的一个接口。这个接口提供了很多用于操作列表的方法,下面是一些主要的:
add(Object o)
: 在列表的末尾添加一个元素。addAll(Collection> c)
: 在列表的末尾添加一个集合的所有元素。get(int index)
: 获取指定索引位置的元素。size()
: 获取列表的大小。set(int index, Object element)
: 设置指定索引位置的元素。remove(Object o)
: 移除第一个出现的指定元素。removeAll(Collection> c)
: 移除所有出现的指定集合的元素。clear()
: 移除所有元素。contains(Object o)
: 检查列表是否包含指定的元素。addFirst(Object o)
: 在列表的头部添加一个元素。addLast(Object o)
: 在列表的尾部添加一个元素。removeFirst(Object o)
: 移除第一个出现的指定元素并返回它。removeLast(Object o)
: 移除最后一个出现的指定元素并返回它。move(int sourceIndex, int destIndex)
: 将指定索引位置的元素移动到另一个索引位置。containsAll(Collection> c)
: 检查列表是否包含所有指定的元素。indexOf(Object o)
: 返回指定元素在列表中的索引,如果列表不包含该元素则返回 -1。lastIndexOf(Object o)
: 返回指定元素在列表中的最后一个索引,如果列表不包含该元素则返回 -1。sort(Comparator super E> c)
: 根据给定的比较器对列表进行排序。stream()
, parallelStream()
: 返回一个流,以便进行流式处理。RList
还提供了很多其他方法,如获取子列表、获取随机元素等。这只是 RList
接口中的一部分方法,实际上它还提供了更多的功能和操作。你可以查看 Redisson 的官方文档或源代码来获取更详细的信息和使用示例。
import org.redisson.Redisson;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
public class ListExamples {
public static void main(String[] args) {
// 默认连接上 127.0.0.1:6379
RedissonClient client = Redisson.create();
// RList 继承了 java.util.List 接口
RList<String> nameList = client.getList("nameList");
nameList.clear();
nameList.add("bingo");
nameList.add("name");
nameList.add("https://github.com/demo");
nameList.remove(-1);
boolean contains = nameList.contains("name");
System.out.println("List size: " + nameList.size());
System.out.println("Is list contains name 'name': " + contains);
nameList.forEach(System.out::println);
client.shutdown();
}
}
运行上面的代码时,可以获得以下输出:
List size: 2
Is list contains name 'name': true
bingo
yanglbme
RedissonClient中的RMap是一个用于在Redis中存储键值对数据的接口。它提供了许多用于操作映射表的方法,下面是一些主要的:
put(K key, V value)
: 添加或更新一个键值对。putAll(Map extends K, ? extends V> m)
: 添加或更新一个映射表中的所有键值对。get(Object key)
: 获取指定键的值。get(Object key, V defaultValue)
: 获取指定键的值,如果键不存在则返回默认值。remove(Object key)
: 删除指定键及其对应的值。containsKey(Object key)
: 检查映射表中是否包含指定的键。containsValue(Object value)
: 检查映射表中是否包含指定的值。keySet()
: 返回映射表中所有键的集合。values()
: 返回映射表中所有值的集合。entrySet()
: 返回映射表中所有键值对的集合。putIfAbsent(K key, V value)
: 如果指定键不存在,则添加或更新一个键值对。replace(K key, V value)
: 替换指定键的值。如果键不存在,则不执行任何操作。replace(K key, V oldValue, V newValue)
: 替换与指定旧值匹配的所有键的值。sort(Comparator super K> c)
: 根据给定的比较器对映射表的键进行排序。stream()
, parallelStream()
: 返回一个流,以便进行流式处理。RMap
还提供了很多其他方法,如获取子映射表、获取随机键或值等。这只是 RMap
接口中的一部分方法,实际上它还提供了更多的功能和操作。你可以查看 Redisson 的官方文档或源代码来获取更详细的信息和使用示例。
import org.redisson.Redisson;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
public class MapExamples {
public static void main(String[] args) {
// 默认连接上127.0.0.1:6379
RedissonClient client = Redisson.create();
// RMap 继承了 java.util.concurrent.ConcurrentMap 接口
RMap<String, String> map = client.getMap("personalInfo");
map.put("name", "name");
map.put("address", "adress");
map.put("link", "https://link.com/demo");
boolean contains = map.containsKey("link");
System.out.println("Map size: " + map.size());
System.out.println("Is map contains key 'link': " + contains);
String value = map.get("name");
System.out.println("Value mapped by key 'name': " + value);
boolean added = map.putIfAbsent("link", "https://doocs.github.io") == null;
System.out.println("Is value mapped by key 'link' added: " + added);
client.shutdown();
}
}
运行上面的代码时,将会看到以下输出:
Map size: 3
Is map contains key 'link': true
Value mapped by key 'name': name
Is value mapped by key 'link' added: false
RedissonClient中的RLock是一个用于在Redis中实现分布式锁的接口。它提供了许多用于操作锁的方法,下面是一些主要的:
lock()
: 获取锁,如果锁已被其他客户端持有,则当前客户端会阻塞等待。lock(long leaseTime, TimeUnit unit)
: 获取锁,并设置锁的租用时间。租用时间过后,锁会自动释放。unlock()
: 释放锁。在调用unlock()方法之前,必须确保已经通过调用lock()方法获取了锁。tryLock()
: 尝试获取锁,如果锁未被其他客户端持有,则立即获取锁并返回true,否则返回false。tryLock(long waitTime, long leaseTime, TimeUnit unit)
: 尝试获取锁,如果锁未被其他客户端持有,则等待指定的等待时间后获取锁,并设置锁的租用时间。如果等待时间内无法获取锁,则返回false。lock()
和 tryLock()
方法可以用于重入锁,这意味着同一个线程可以多次获取同一个锁,而不会导致死锁。isLocked()
: 检查锁是否被当前客户端持有。isHeldByCurrentThread()
: 检查当前线程是否持有该锁。getHoldCount()
: 返回当前线程对锁的持有次数。getQueueLength()
: 返回等待获取该锁的线程数。expireAfterWrite
和expireAfterAccess
方法为锁设置过期时间。这样,如果一个客户端在一段时间内无法释放锁(例如由于崩溃),那么锁会自动释放。delete
和rename
方法可以删除或重命名锁。setFair
方法可以设置锁的公平性。公平锁会按照线程请求锁的顺序来授予锁,而非公平锁则不会保证这个顺序。这只是 RLock 接口中的一部分方法,实际上它还提供了更多的功能和操作。你可以查看 Redisson 的官方文档或源代码来获取更详细的信息和使用示例。
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
public class LockExamples {
public static void main(String[] args) throws InterruptedException {
// 默认连接上127.0.0.1:6379
RedissonClient client = Redisson.create();
// RLock 继承了 java.util.concurrent.locks.Lock 接口
RLock lock = client.getLock("lock");
lock.lock();
System.out.println("lock acquired");
Thread t = new Thread(() -> {
RLock lock1 = client.getLock("lock");
lock1.lock();
System.out.println("lock acquired by thread");
lock1.unlock();
System.out.println("lock released by thread");
});
t.start();
t.join(1000);
lock.unlock();
System.out.println("lock released");
t.join();
client.shutdown();
}
}
此代码将产生以下输出:
lock acquired
lock released
lock acquired by thread
lock released by thread
RedissonClient中的RAtomicLong是一个在Redis中实现的分布式原子长整型数据的接口。它提供了许多用于操作原子长整型数据的方法,下面是一些主要的:
incrementAndGet()
: 原子地增加当前值,并返回增加后的值。decrementAndGet()
: 原子地减少当前值,并返回减少后的值。set(long newValue)
: 原子地设置新的值。get()
: 获取当前值。compareAndSet(long expect, long update)
: 原子地比较当前值与期望值,如果相等,则将当前值更新为新值,并返回true,否则不执行任何操作并返回false。addAndGet(long delta)
: 原子地增加当前值,并返回增加后的值。getAndSet(long newValue)
: 原子地设置新的值,并返回旧值。getAndAdd(long delta)
: 原子地增加当前值,并返回增加前的值。getOffset
和setOffset
方法可以获取和设置偏移量,这可以用于实现原子操作。这只是 RAtomicLong 接口中的一部分方法,实际上它还提供了更多的功能和操作。你可以查看 Redisson 的官方文档或源代码来获取更详细的信息和使用示例。
import org.redisson.Redisson;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;
public class AtomicLongExamples {
public static void main(String[] args) {
// 默认连接上127.0.0.1:6379
RedissonClient client = Redisson.create();
RAtomicLong atomicLong = client.getAtomicLong("myLong");
System.out.println("Init value: " + atomicLong.get());
atomicLong.incrementAndGet();
System.out.println("Current value: " + atomicLong.get());
atomicLong.addAndGet(10L);
System.out.println("Final value: " + atomicLong.get());
client.shutdown();
}
}
此代码的输出将是:
Init value: 0
Current value: 1
Final value: 11
RedissonClient中的RQueue是一个在Redis中实现的分布式队列的接口。它提供了许多用于操作队列的方法,下面是一些主要的:
add(E e)
: 将指定的元素添加到队列的末尾。offer(E e)
: 将指定的元素添加到队列的末尾,如果队列已满,则不执行任何操作。remove()
: 移除并返回队列的头元素。如果队列为空,则不执行任何操作。poll()
: 移除并返回队列的头元素,如果队列为空,则返回null。element()
: 获取但不移除队列的头元素,如果队列为空,则抛出异常。peek()
: 获取但不移除队列的头元素,如果队列为空,则返回null。contains(Object o)
: 检查队列是否包含指定的元素。clear()
: 移除队列中的所有元素。size()
: 返回队列中的元素个数。take
和 put
,它们可以使当前线程等待直到获取或添加元素为止。这只是 RQueue 接口中的一部分方法,实际上它还提供了更多的功能和操作。你可以查看 Redisson 的官方文档或源代码来获取更详细的信息和使用示例。
RedissonClient
中的 RPubSub
是一个接口,它代表 Redis 的发布/订阅功能。Redis 的发布/订阅模型允许消息的生产者(发布者)发送消息到一个或多个消费者(订阅者)而无需知道它们是谁。在 Redisson 中,RPubSub
提供了一套 API 来实现这种发布/订阅模式。
以下是 RPubSub
提供的主要方法:
subscribe(String... channelNames)
: 订阅一个或多个频道。当有消息发布到这些频道时,订阅者会收到这些消息。psubscribe(String... patternChannelNames)
: 订阅一个或多个模式频道。模式频道使用模式匹配来过滤消息。unsubscribe(String... channelNames)
: 取消订阅一个或多个频道。punsubscribe(String... patternChannelNames)
: 取消订阅一个或多个模式频道。RPubSub
本身并不直接提供发布消息的方法。发布消息通常是通过 RTopic
接口来完成的,你可以通过 RedissonClient
的 getTopic
方法来获取一个 RTopic
实例,然后调用其 publish
方法来发布消息。addListener(MessageListener super V> listener)
: 添加一个消息监听器,该监听器会在接收到订阅的频道或模式频道的消息时被调用。removeListener(MessageListener super V> listener)
: 移除一个消息监听器。getChannelName()
: 获取当前订阅的频道名称(仅适用于单个频道的订阅者)。getPatternChannelName()
: 获取当前订阅的模式频道名称(仅适用于模式频道的订阅者)。RPubSub
通常与 RTopic
一起使用,RTopic
代表一个可以发布消息的频道。你可以通过 RedissonClient
的 getTopic
方法获取一个 RTopic
实例,并使用它来发布消息。
下面是一个简单的使用示例:
RedissonClient redisson = Redisson.create();
// 获取一个 RTopic 实例
RTopic<String> topic = redisson.getTopic("anyChannel");
// 创建一个 RPubSub 实例并订阅频道
RPubSub<String> pubSub = redisson.getPubSub();
pubSub.addListener(new MessageListener<String>() {
@Override
public void onMessage(String channel, String message) {
System.out.println("Received message: " + message + " from channel: " + channel);
}
});
// 订阅频道
pubSub.subscribe("anyChannel");
// 发布消息
topic.publish("Hello, Redis!");
// ... 在某个时刻取消订阅
pubSub.unsubscribe("anyChannel");
// 关闭 Redisson 客户端
redisson.shutdown();
需要注意的是,上面的示例代码中,发布和订阅操作是在同一个进程内完成的,但在实际应用中,发布者和订阅者通常是分布在不同进程或机器上的。此外,订阅操作通常是阻塞的,这意味着订阅者会一直监听频道直到它被取消订阅或程序被终止。在实际应用中,你可能需要在一个单独的线程中处理订阅逻辑。
RLock lock = redissonClient.getLock("myLock");
lock.lock();
try {
// 在这里执行需要互斥的操作
} finally {
lock.unlock();
}
RList<String> list = redissonClient.getList("myList");
list.add("item1");
list.add("item2");
list.add("item3");
RMap<String, String> map = redissonClient.getMap("myMap");
map.put("key1", "value1");
map.put("key2", "value2");
String value = map.get("key1");
RMap<String, Person> map = redissonClient.getMap("myHashTable");
Person person = new Person("John", 30);
map.put("key1", person);
Person value = map.get("key1");
RQueue<String> queue = redissonClient.getQueue("myQueue");
queue.offer("item1");
queue.offer("item2");
String item = queue.poll(); // 获取并移除队列的头元素
RPubSub<String, String> pubSub = redissonClient.getPubSub("myPubSub");
pubSub.subscribe("channel1", new MessageListener<String>() { // 订阅一个频道并设置监听器
@Override
public void onMessage(String channel, String message) {
// 处理消息的逻辑
}
});
pubSub.publish("channel1", "message1"); // 发布一条消息到指定的频道
ring item = queue.poll(); // 获取并移除队列的头元素
1. **获取分布式发布订阅**:RedissonClient提供了分布式发布订阅的实现,这可以帮助我们实现消息的发布和订阅。以下是使用发布订阅的示例代码:
```java
RPubSub pubSub = redissonClient.getPubSub("myPubSub");
pubSub.subscribe("channel1", new MessageListener() { // 订阅一个频道并设置监听器
@Override
public void onMessage(String channel, String message) {
// 处理消息的逻辑
}
});
pubSub.publish("channel1", "message1"); // 发布一条消息到指定的频道
以上是RedissonClient中的一些常用方法,实际上RedissonClient还提供了许多其他功能和操作,你可以查看Redisson的官方文档或源代码来获取更详细的信息和使用示例。