Redis数据库基础知识,类型知识点梳理~
Redis是一种基于内存的开源键值对存储系统,支持多种数据结构类型。
SET key value
:设置键值。GET key
:获取键值。INCR key
/ DECR key
:对值进行原子递增/递减操作。APPEND key value
:追加字符串。LPUSH key value
/ RPUSH key value
:从左/右插入元素。LPOP key
/ RPOP key
:从左/右弹出元素。LRANGE key start stop
:获取指定范围内的元素。SADD key member
:添加元素。SREM key member
:删除元素。SMEMBERS key
:获取所有元素。SINTER key1 key2
:求交集。SUNION key1 key2
:求并集。SDIFF key1 key2
:求差集。ZADD key score member
:添加元素及其分数。ZRANGE key start stop [WITHSCORES]
:按排名获取元素。ZREM key member
:删除元素。ZRANK key member
:获取元素的排名。HSET key field value
:设置字段的值。HGET key field
:获取字段的值。HGETALL key
:获取所有字段和值。HDEL key field
:删除字段。PFADD key element
:添加元素。PFCOUNT key
:返回基数估算结果。SETBIT key offset value
:设置位的值。GETBIT key offset
:获取位的值。BITCOUNT key [start end]
:统计特定位范围内1的数量。GEOADD key longitude latitude member
:添加地理位置。GEORADIUS key longitude latitude radius unit
:查询指定半径内的成员。GEODIST key member1 member2 unit
:计算两个成员之间的距离。XADD key * field value [field value ...]
:添加日志条目。XRANGE key start end
:按范围获取条目。XREAD COUNT count STREAMS key ID
:读取新条目。XGROUP CREATE key groupname id
:创建消费组。使用分布式锁时,要考虑锁的超时时间、锁的可重入性、锁的安全性等方面的问题,以确保系统的正确性和性能。
Redis中的分布式锁类型:
SETNX
命令来实现锁的获取,当某个客户端成功地将一个特定的键设置为锁时,其他客户端无法再设置该键,从而实现分布式锁的效果。Redlock算法
是由Redis的作者提出的一种分布式锁算法,它通过在多个独立的Redis实例上加锁来实现分布式锁。Redisson
实现的分布式锁利用了Redis的特性,并且内置了看门狗机制,并且Redisson内部已经处理好了看门狗机制。当你获取到锁后,Redisson会启动一个后台线程,周期性地延长锁的过期时间(每隔10秒),确保锁在持有期间不会因为过期而被自动释放。这个机制有效地防止了因意外长时间持锁导致的死锁问题。 SET key value PX milliseconds NX
命令来实现。DEL key
命令删除锁的键。(1)引入Redisson的依赖。
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.3</version>
</dependency>
(2)配置Redisson客户端。
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
public class RedissonConfig {
public static RedissonClient createClient() {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
}
(3)通过Redisson客户端来获取和释放分布式锁。
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
public class DistributedLockExample {
public static void main(String[] args) {
RedissonClient redissonClient = RedissonConfig.createClient();
// 获取名为 "myLock" 的锁
RLock lock = redissonClient.getLock("myLock");
try {
// 尝试获取锁,等待时间为100秒,如果获取成功,则持有锁10秒
if (lock.tryLock(100, 10, TimeUnit.SECONDS)) {
try {
// 锁获取成功,执行需要加锁的业务逻辑
System.out.println("锁定成功,执行业务逻辑");
} finally {
// 释放锁
lock.unlock();
}
} else {
System.out.println("未能获取到锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
redissonClient.shutdown();
}
}
}
使用分布式锁场景:
Redis中的事务是一组命令的原子性操作,可以保证这组命令要么全部执行成功,要么全部失败。Redis事务使用
MULTI、EXEC、DISCARD和WATCH
等命令进行控制。
Redis事务命令类型:
Redis事务使用场景:
WATCH
命令和事务结合,可以实现乐观锁机制。在操作某个键之前,先通过WATCH
命令监视该键,如果在执行事务期间该键的值被修改,则事务执行失败。可以利用这个特性实现乐观锁来保证并发操作的一致性。 BRPOP
命令可以实现简单的队列功能。多个客户端可以并发地将任务推入队列,然后通过事务的方式一次性取出多个任务进行处理。Redis事物使用Demo:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;
public class RedisTransactionExample {
public static void main(String[] args) {
// 使用Jedis库连接Redis服务器
Jedis jedis = new Jedis("localhost", 6379);
// 开启事务
Transaction transaction = jedis.multi();
// 将多个命令添加到事务中
transaction.set("key1", "value1");
transaction.set("key2", "value2");
// 执行事务,并返回执行结果
Response<String> response1 = transaction.get("key1");
Response<String> response2 = transaction.get("key2");
// 执行事务
// 在事务中,命令并不会立即执行,而是放入队列中等待exec()命令执行
transaction.exec();
// 获取执行结果
String value1 = response1.get();
String value2 = response2.get();
System.out.println("Value of key1: " + value1);
System.out.println("Value of key2: " + value2);
// 关闭连接
jedis.close();
}
}
ps:Redis事务并不是严格的ACID事务,它没有提供隔离级别和回滚日志等特性。在Redis事务中,如果某个命令执行失败,后续的命令仍然会继续执行,而不会回滚到事务开始之前的状态,对于强一致性要求较高的场景,Redis事务可能不适用。
Redis事务适用于对数据一致性要求较低但需要确保操作顺序的场景。对于更复杂的事务管理和更高的数据一致性要求,可能需要考虑使用关系型数据库或其他解决方案。
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class RedisTransactionExample {
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost");
// 开启事务
Transaction transaction = jedis.multi();
try {
// 将多个命令打包到一个事务中
transaction.incr("counter");
transaction.rpush("queue", "message1");
transaction.set("key1", "value1");
// 执行事务
transaction.exec();
} catch (Exception e) {
e.printStackTrace();
// 处理事务执行失败的情况,放弃事务
transaction.discard();
} finally {
jedis.close();
}
}
}
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class RedisTransactionExample {
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost");
// 开启事务
Transaction transaction = jedis.multi();
try {
// 将多个命令按顺序打包到一个事务中
transaction.set("key1", "value1");
transaction.set("key2", "value2");
transaction.incr("counter");
// 执行事务
transaction.exec();
} catch (Exception e) {
e.printStackTrace();
// 处理事务执行失败的情况,放弃事务
transaction.discard();
} finally {
jedis.close();
}
}
}
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class RedisTransactionExample {
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost");
// 开启事务
Transaction transaction = jedis.multi();
try {
// 将多个命令打包到一个事务中
transaction.set("key1", "value1");
transaction.incr("counter");
// 故意引入错误的命令(例如对不存在的哈希字段进行递增)
transaction.hincrBy("nonexistent_hash", "field", 1);
// 执行事务
transaction.exec();
} catch (Exception e) {
e.printStackTrace();
// 处理事务执行失败的情况,放弃事务
transaction.discard();
} finally {
jedis.close();
}
}
}
无论世界如何纷扰,心中有梦,便有了方向
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。