spring-boot-starter-data-redis 翻译官方文档 5.10 - 5.13

参考文档: https://docs.spring.io/spring-data/redis/docs/2.0.3.RELEASE/reference/html/

Redis中文教程: http://www.redis.net.cn/tutorial/3501.html

5.10. Redis Transactions

Redis通过multi,exec和discard命令提供对事务的支持。 这些操作在RedisTemplate上可用,但RedisTemplate不保证使用相同的连接执行事务中的所有操作。

Spring Data Redis提供SessionCallback接口,以便在需要使用相同连接执行多个操作时使用,就像使用Redis事务时一样。 例如:
//execute a transaction
List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>() {
  public List<Object> execute(RedisOperations operations) throws DataAccessException {
    operations.multi();
    operations.opsForSet().add("key", "value1");

    // This will contain the results of all ops in the transaction
    return operations.exec();
  }
});
System.out.println("Number of items added to set: " + txResults.get(0));

在返回之前,RedisTemplate将使用它的value, hash key 序列化器来反序列化exec的所有结果。 还有一个额外的exec方法,允许您为事务结果传递自定义序列化程序。

版本1.1中的RedisConnection和RedisTemplate的exec方法已经作了重大更改。 以前,这些方法直接从connectors返回事务结果。 这意味着数据类型通常不同于RedisConnection方法返回的数据类型。 例如,zAdd返回一个boolean,表明该元素已被添加到sorted set中。 大多数connectors将这个值作为一个long值返回,并且Spring Data Redis执行转换。 另一个常见的区别是大多数连接器都会返回一个状态回复(通常是字符串“OK”),以执行set等操作。 这些回复通常被Spring Data Redis丢弃。 在1.1之前,这些转换不是对exec的结果执行的。此外,结果并未在RedisTemplate中反序列化,因此它们通常包含原始字节数组。 如果此更改中断了您的应用程序,可以在RedisConnectionFactory上将convertPipelineAndTxResults设置为false以禁用此行为。

5.10.1. @Transactional Support

事务Transaction的功能默认是禁用的,必须通过设置setEnableTransactionSupport(true)为每个正在使用的RedisTemplate显式启用。这将RedisConnection强制绑定到当前线程并触发MULTI。 如果事务完成没有错误,EXEC被调用,否则DISCARD。 一旦进入MULTI,RedisConnection会对写入操作进行排队,所有只读操作(例如KEYS)将被传送到新的(非线程绑定的)RedisConnection。

/** Sample Configuration **/
@Configuration
public class RedisTxContextConfiguration {
  @Bean
  public StringRedisTemplate redisTemplate() {
    StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory());
    // explicitly enable transaction support
    template.setEnableTransactionSupport(true);
    return template;
  }

  @Bean
  public PlatformTransactionManager transactionManager() throws SQLException {
    return new DataSourceTransactionManager(dataSource());
  }

  @Bean
  public RedisConnectionFactory redisConnectionFactory( // jedis || lettuce);

  @Bean
  public DataSource dataSource() throws SQLException { // ... }
}
/** Usage Constrainsts **/

// executed on thread bound connection
template.opsForValue().set("foo", "bar");

// read operation executed on a free (not tx-aware)
connection template.keys("*");

// returns null as values set within transaction are not visible
template.opsForValue().get("foo");

5.11. Pipelining

Redis为管道提供支持,其中包括向服务器发送多条命令,而无需等待答复,然后在一个单独的步骤中读取答复。当您需要连续发送多个命令时,管道传输可以提高性能,例如将多个元素添加到同一个List列表中。


Spring Data Redis提供了多个用于在管道中执行命令的RedisTemplate方法。 如果您不关心管道操作的结果,则可以使用标准的execute方法,并为pipeline参数传递true。 executePipelined方法将在管道中执行提供的RedisCallback或SessionCallback并返回结果。 例如:

//pop a specified number of items from a queue
List<Object> results = stringRedisTemplate.executePipelined(
  new RedisCallback<Object>() {
    public Object doInRedis(RedisConnection connection) throws DataAccessException {
      StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
      for(int i=0; i< batchSize; i++) {
        stringRedisConn.rPop("myqueue");
      }
    return null;
  }
});
上面的例子执行的是批量右侧弹出管道队列中的数据元素。结果List列表包含所有弹出的元素。在返回结果之前,RedisTemplate使用其hash-value, hash-key和hash-value-serializers对所有结果进行反序列化,因此上面示例中返回的元素将是Strings。 还有一些executePipelined方法允许您为管道结果传递自定义序列化程序。

请注意,从RedisCallback返回的值必须为空,因为此值将被丢弃,以便返回管道命令的结果。

版本1.1中对RedisConnection的closePipeline方法做出了重大更改。 此前,此方法直接从connectors返回流水线操作的结果。 这意味着数据类型通常与RedisConnection方法返回的数据类型不同。 例如,zAdd返回一个布尔值,表明该元素已被添加到已排序的集合中。 大多数连接器将这个值作为一个long值返回,并且Spring Data Redis执行转换。 另一个常见的区别是大多数连接器都会返回一个状态回复(通常是字符串“OK”),以执行set等操作。 这些回复通常被Spring Data Redis丢弃。 在1.1之前,这些转换不是对closePipeline的结果执行的。如果此更改中断了您的应用程序,则可以在RedisConnectionFactory上将convertPipelineAndTxResults设置为false以禁用此行为。

5.12. Redis Scripting

Redis 2.6及更高版本通过eval和evalsha命令为Lua脚本的执行提供支持。 Spring Data Redis为处理序列化的脚本执行提供高级抽象,并自动使用Redis脚本缓存。


脚本可以通过RedisTemplate和ReactiveRedisTemplate的执行方法运行。两者都使用可配置的ScriptExecutor/ReactiveScriptExecutor来运行提供的脚本。默认情况下,ScriptExecutor负责序列化提供的键和参数并反序列化脚本结果。这是通过模板的键和值序列化器完成的。还有一个额外的重载允许您为脚本参数和结果传递自定义序列化器。

默认的ScriptExecutor通过检索脚本的SHA1并尝试首先运行evalsha来优化性能,如果脚本尚不存在于Redis脚本缓存中,则会回退到eval。

以下是一个使用Lua脚本执行常见“检查并设置”场景的示例。对于Redis脚本来说,这是一个理想的用例,因为它要求我们以原子方式执行一组命令,并且一个命令的行为受另一个命令的影响。


@Bean
public RedisScript<Boolean> script() {

  ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource("META-INF/scripts/checkandset.lua");
  return RedisScript.of(scriptSource, Boolean.class);
}
public class Example {

  @Autowired
  RedisScript<Boolean> script;

  public boolean checkAndSet(String expectedValue, String newValue) {
    return redisTemplate.execute(script, singletonList("key"), asList(expectedValue, newValue));
  }
}
 -- checkandset.lua local
 current = redis.call('GET', KEYS[1])
 if current == ARGV[1]
   then redis.call('SET', KEYS[1], ARGV[2])
   return true
 end
 return false
上面的代码配置RedisScript指向名为checkandset.lua的文件,该文件预计会返回一个布尔值。脚本resultType应该是Long,Boolean,List或反序列化值类型之一。 如果脚本返回丢弃状态(即“OK”),它也可以为空。 在应用程序上下文中配置DefaultRedisScript的单个实例是非常理想的,以避免在每次脚本执行时重新计算脚本的SHA1。

上面的checkAndSet方法执行脚本可以作为事务或管道的一部分在SessionCallback中执行。 有关更多信息,请参阅Redis事务和管道传输。

Spring Data Redis提供的脚本支持还允许您使用Spring Task和Scheduler抽象计划定期执行Redis脚本。 有关更多详细信息,请参阅Spring Framework文档。


5.13. Support Classes

Package org.springframework.data.redis.support提供各种可重用组件,这些组件依赖Redis作为后备存储。目前,该软件包在Redis之上包含各种基于JDK的界面实现,如原子计数器和JDK集合。

原子计数器可以轻松地包装Redis密钥增量,而集合允许以最小的存储空间或API泄漏轻松管理Redis密钥:特别是RedisSet和RedisZSet接口可以轻松访问Redis支持的集合操作,例如交集intersection和联合union,而RedisList在Redis之上实现了List,Queue和Deque契约(及其等效的同级同胞),将存储作为FIFO(先进先出),LIFO(后进先出)或采用最小配置的集合:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="queue" class="org.springframework.data.redis.support.collections.DefaultRedisList">
    <constructor-arg ref="redisTemplate"/>
    <constructor-arg value="queue-key"/>
  </bean>

</beans>
public class AnotherExample {

  // injected
  private Deque<String> queue;

  public void addTag(String tag) {
    queue.push(tag);
  }
}

如上例所示,使用代码与实际的存储实现分离 - 事实上,没有指出在下面使用Redis的情况。 这使得从开发到生产环境变得透明并且极大地提高了可测试性(Redis实现可以被在内存中的一个所取代)。

5.13.1. Support for Spring Cache Abstraction - 2.0中的改变
Spring Redis通过org.springframework.data.redis.cache包提供了Spring缓存抽象的实现。 要使用Redis作为后台实现,只需将RedisCacheManager添加到您的配置中即可:
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
	return RedisCacheManager.create(connectionFactory);
}

RedisCacheManager行为可以通过RedisCacheManagerBuilder配置,允许设置默认的RedisCacheConfiguration,事务行为和预定义的缓存。

RedisCacheManager cm = RedisCacheManager.builder(connectionFactory)
	.cacheDefaults(defaultCacheConfig())
	.initialCacheConfigurations(singletonMap("predefined", defaultCacheConfig().disableCachingNullValues()))
	.transactionAware()
	.build();

通过RedisCacheManager创建的RedisCache的行为通过RedisCacheConfiguration定义。该配置允许设置密钥到期时间,前缀和RedisSerializer以转换为二进制存储格式和从二进制存储格式转换。 如上所示,RedisCacheManager允许定义每个缓存库上的配置。

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
    .entryTtl(Duration.ofSeconds(1))
	.disableCachingNullValues();

RedisCacheManager默认使用无锁 Lock-free RedisCacheWriter来读取和写入二进制值。无锁缓存提高了吞吐量。 缺少入口锁定可能会导致putIfAbsent和clean方法的重叠非原子命令,因为那些方法需要将多个命令发送到Redis。 锁定副本通过设置显式锁定键explicit lock key并检查是否存在此键来防止命令重叠,这会导致额外的请求和潜在的命令等待时间。

可以选择加入锁定行为如下:

RedisCacheManager cm = RedisCacheManager.build(RedisCacheWriter.lockingRedisCacheWriter())
	.cacheDefaults(defaultCacheConfig())
	...
Table 4. RedisCacheManager defaults
SettingValue

Cache Writer

non locking

Cache Configuration

RedisCacheConfiguration#defaultConfiguration

Initial Caches

none

Trasaction Aware

no

Table 5. RedisCacheConfiguration defaults
Key Expirationnone

Cache null

yes

Prefix Keys

yes

Default Prefix

the actual cache name

Key Serializer

StringRedisSerializer

Value Serializer

JdkSerializationRedisSerializer

Conversion Service

DefaultFormattingConversionService with default cache key converters
















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值