文章摘要(AI生成)
Spring Redis在多个领域中展现了高效性和实用性,如电信运营系统、购物网站性能优化、高校Web服务器会话保持等。Redis作为高性能数据库,在提高数据读写性能、解决系统负荷过高问题方面发挥重要作用,尤其在处理高并发请求、提升系统响应速度方面表现突出。在Spring Boot框架下,Redis被广泛应用于缓存技术,解决了数据同步问题、提升了搜索查询效率。Redis集群配置管理平台和原生Redis集群的优化体现了其强大能力和灵活性。使用Spring Redis时,需要添加依赖、配置连接信息、创建RedisTemplate Bean,并可选择使用Spring Data Redis进行操作或使用Spring Cache进行缓存管理。Redis执行命令,连接redis方法和Redis连接获取等方面展示了Redis在处理大规模数据存储和高并发访问需求时的机制和实现方式。Spring Redis的集成与应用提升了系统性能和用户体验,是现代软件开发的重要组成部分。
Spring Redis的集成和应用在多个领域中展现了其高效性和实用性。从电信运营系统、购物网站性能优化、高校Web服务器会话保持、大数据交易集市平台、企业一卡通系统、下沉市场交易平台、车辆寄售后台系统、在线教育平台、高并发Web场景下的缓存研究与设计等不同场景的应用研究表明,Redis作为一种高性能的键值对数据库,在提高数据读写性能、解决系统负荷过高问题方面发挥了重要作用。
特别是在处理高并发请求、提升系统响应速度和吞吐量方面,Redis显示出了其独特的优势。例如,在基于Nginx和Redis架构的高并发框架设计与研究中,通过利用Redis映射服务模式处理数据库,进一步提升了集群服务器的响应能力。此外,Redis集群配置管理平台的设计与实现,以及原生redis集群的优化与实现,都体现了Redis在处理大规模数据存储和高并发访问需求时的强大能力和灵活性。
在Spring Boot框架下,Redis被广泛应用于缓存技术,以解决数据同步问题、提升搜索查询效率、实现线上全程无纸化信息存储等,这些应用不仅提高了系统的运行效率,也简化了开发过程,使得系统集成更加简单快捷。
Spring Redis的集成和应用在提高系统性能、优化用户体验方面具有显著效果,是现代软件开发中不可或缺的一部分。
在我们使用spring redis时,通常需要以下步骤:
- 添加Redis依赖到项目的pom.xml 文件中,通常使用
spring-boot-starter-data-redis
依赖。 - 配置Redis连接信息,这可以通过编辑properties或yml配置文件来完成。
- 创建
RedisTemplate
Bean,这是进行Redis操作的关键组件。 - 可以选择使用Spring Data Redis进行数据库操作,或使用Spring Cache进行缓存管理。
这篇文章我们来看下Spring redis是如何运作的.
Redis命令执行-RedisTemplate
查看RedisTemplate
的类关系图,我们可以看到它实现了RedisOperations
接口。RedisOperations
接口具有泛型参数K和V,用于指定键和值的类型。它被用于操作Redis数据库,提供了多种方法来执行Redis的操作,例如设置和获取键值对、执行事务、操作列表、集合、有序集合等。
RedisTemplate
的连接池由父类RedisAccessor
提供,而RedisTemplate
中则提供对应的键值对序列化器以及对应的redis命令执行器
实例初始化
RedisTemplate
初始化时指定了其默认的序列化器和redis脚本执行器。其序列化器使用了JdkSerializationRedisSerializer
:
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
其由spring默认的序列化器DefaultSerializer
和DefaultDeserializer
提供。
除了上述两个,为了支持对redis的写入,RedisTemplate
还对Redis不同数据类型的操作进行了初始化:
//普通键值对
private final ValueOperations<K, V> valueOps = new DefaultValueOperations<>(this);
//数组
private final ListOperations<K, V> listOps = new DefaultListOperations<>(this);
//集合
private final SetOperations<K, V> setOps = new DefaultSetOperations<>(this);
//流
private final StreamOperations<K, ?, ?> streamOps = new DefaultStreamOperations<>(this,
ObjectHashMapper.getSharedInstance());
//有序集合
private final ZSetOperations<K, V> zSetOps = new DefaultZSetOperations<>(this);
//地理位置
private final GeoOperations<K, V> geoOps = new DefaultGeoOperations<>(this);
//HyperLogLog
private final HyperLogLogOperations<K, V> hllOps = new DefaultHyperLogLogOperations<>(this);
private final ClusterOperations<K, V> clusterOps = new DefaultClusterOperations<>(this);
连接redis
方法-execute
RedisTemplate
中实现了连接redis
命令的执行方法 -execute
方法:
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline)
其主要逻辑为:
- 验证模板是否已初始化和action对象是否为空。
- 获取Redis连接工厂和连接。调用
RedisAccessor
获取连接工厂。 - 根据是否已存在连接和是否启用事务支持,对连接进行预处理(
RedisTemplate
不做任何处理,留给子类拓展)。 - 根据是否启用管道和当前是否已使用管道,决定是否打开管道。
- 根据是否暴露连接,创建一个连接代理或直接使用处理后的连接执行Redis操作,并获取结果。
- 如果启用了管道且之前未使用管道,则关闭管道。
- 对结果进行后处理,并返回处理后的结果。
- 释放Redis连接。
Redis连接获取–RedisConnectionUtils.doGetConnection()
该方法通过TransactionSynchronizationManager
对我们的RedisConnectionFactory
进行管理。通过事务管理器来获取或绑定我们的redis
连接:
- 检查当前事务或当前线程是否已绑定连接。如果是,则使用已有的连接。
- 如果没有找到连接,并且allowCreate参数为true,则创建一个新的连接。
- 如果bind参数为true,将连接绑定到当前线程。
- 如果事务支持开启并且存在活跃的事务,则创建一个连接的代理。
- 在事务完成时,通过同步机制自动释放绑定的连接。
TransactionSynchronizationManager
是Spring框架中处理事务同步的类。它是通过使用线程本地变量来存储和管理与事务相关的资源和同步器的。具体功能如下:
- 管理事务相关的资源:通过
bindResource
和unbindResource
方法来绑定和解绑事务相关的资源,例如数据库连接等。这些资源会与当前线程绑定,确保在事务中对资源的访问是线程安全的。- 管理事务同步器:通过
initSynchronization
、registerSynchronization
和clearSynchronization
方法来初始化、注册和清除事务同步器。事务同步器是在事务执行过程中执行特定操作的回调接口,例如更新缓存、发送消息等。- 提供事务相关信息:通过
getResourceMap
、hasResource
和getResource
等方法可以获取当前事务中绑定的资源信息;通过isSynchronizationActive
、getSynchronizations
等方法可以获取当前事务中注册的同步器信息。- 管理事务属性:通过
setCurrentTransactionName
、setCurrentTransactionReadOnly
和setCurrentTransactionIsolationLevel
等方法可以设置当前事务的名称、只读属性和隔离级别;通过相应的get方法可以获取这些属性的值。- 清理线程本地变量:通过clear方法可以清除当前线程中绑定的资源、注册的同步器和事务属性等信息。
- 总之,
TransactionSynchronizationManager
是Spring事务管理的重要组成部分,它提供了对事务相关资源和同步器的管理能力,以及获取事务属性信息的功能。
Redis命令执行–RedisCallback.doInRedis()
Redis命令执行和结果解析由RedisCallback.doInRedis()
实现,该RedisCallback
接口只提供了这一个方法,而spring redis则提供了对这个方法的两个实现:AbstractOperations
中的ValueDeserializingRedisCallback
内部类和DefaultStreamOperations
中的RecordDeserializingRedisCallback
内部类,分别提供对普通键值读写操作和流式读写操作的支持
ValueDeserializingRedisCallback
具体逻辑:
// utility methods for the template internal methods
abstract class ValueDeserializingRedisCallback implements RedisCallback<V> {
private Object key;
public ValueDeserializingRedisCallback(Object key) {
this.key = key;
}
//对redis中的指定key进行操作,并对返回结果进行反序列化
public final V doInRedis(RedisConnection connection) {
byte[] result = inRedis(rawKey(key), connection);
return deserializeValue(result);
}
//提供不同写操作支持
@Nullable
protected abstract byte[] inRedis(byte[] rawKey, RedisConnection connection);
}
RecordDeserializingRedisCallback
具体逻辑:
abstract class RecordDeserializingRedisCallback implements RedisCallback<List<MapRecord<K, HK, HV>>> {
@SuppressWarnings("unchecked")
public final List<MapRecord<K, HK, HV>> doInRedis(RedisConnection connection) {
//获取该连接的已有的数据集合
List<ByteRecord> raw = inRedis(connection);
if (raw == null) {
return Collections.emptyList();
}
//将获取到的结果反序列化
List<MapRecord<K, HK, HV>> result = new ArrayList<>();
for (ByteRecord record : raw) {
result.add(deserializeRecord(record));
}
return result;
}
//提供流写入的支持
@Nullable
abstract List<ByteRecord> inRedis(RedisConnection connection);
}
写入操作支持-AbstractOperations
AbstractOperations
是RedisTemplate
中用于操作Redis数据的内部抽象类。它提供了一系列方法,用于序列化和反序列化键值对、哈希表等数据,并执行Redis操作。
rawKey
、rawString
、rawValue
、rawValues
、rawHashKey
、rawHashKeys
、rawHashValue
等方法用于序列化键、值和哈希键值。
deserializeValues
、deserializeTupleValues
、deserializeHashKeys
、deserializeHashValues
、deserializeHashMap
等方法用于反序列化值、元组、哈希键和哈希值。
deserializeKey
、deserializeValue
、deserializeString
、deserializeHashKey
、deserializeHashValue
等方法用于反序列化键、值、字符串、哈希键和哈希值。
deserializeGeoResults
法用于反序列化GeoLocation
的GeoResults
。
这些方法主要用于处理Redis操作中涉及的序列化和反序列化逻辑,确保数据在Java对象和Redis存储之间的正确转换。
设置键值对-set
我们以设置键值对为例,看操作对象是如何执行的。键值对操作由DefaultValueOperations
实现:
@Override
public void set(K key, V value) {
byte[] rawValue = rawValue(value);
execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.set(rawKey, rawValue);
return null;
}
});
}
我们可以看到,set方法首先调用rawValue
方法对设置的值进行序列化,然后调用excute
方法(内部直接调用了RedisTemplate
的execute
方法)进行redis写入命令获取对应的redis连接,由通过ValueDeserializingRedisCallback
进行实际命令执行,在执行是通过重写inRedis
方法,在Redis连接中完了对值的写入操作。
读取键值对-get
同样的,在此类中我们也可以找到Redis读取的操作:
@Override
public V get(Object key) {
return execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.get(rawKey);
}
});
}
其同样重写了inRedis
方法,在Redis连接中完了对值的读取操作。而读取后结果的反序列化则又通过ValueDeserializingRedisCallback
中的反序列化器调用实现。
显示存储-StringRedisTemplate
上面我们讲RedisTemplate
的时候,说到其使用Spring中的类序列化器和反序列化进行数据的读写的,这就导致我们无法直接通过我们的原始key在redis中查到对应数据,只能通过调用rawKey
和rawValue
方法对键值对进行序列化后才能在redis上查找。这就导致在问题排查方面比较困难,当让我们也可以手动重新指定序列化器和反序列化器。基于这个问题,Spring提供了StringRedisTeplate
来简化序列化和反序列化过程中带来的成本,官方解释其目的为:以字符串为中心的RedisTemplate
扩展。由于针对 Redis
的大多数操作都是基于字符串的,因此此类提供了一个专用类,该类可最大程度地减少其更通用 template
的配置,尤其是在序列化程序方面。
StringRedisTemplate
首先在构造函数指定了序列化方式:
public StringRedisTemplate() {
setKeySerializer(RedisSerializer.string());
setValueSerializer(RedisSerializer.string());
setHashKeySerializer(RedisSerializer.string());
setHashValueSerializer(RedisSerializer.string());
}
其重写了连接预处理方法,使其返回DefaultStringRedisConnection
,以支持对字符串的读写操作
protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
return new DefaultStringRedisConnection(connection);
}
评论区