前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Data Redis(一)--解析RedisTemplate

Spring Data Redis(一)--解析RedisTemplate

作者头像
kirito-moe
发布2018-04-27 12:02:56
2.2K0
发布2018-04-27 12:02:56
举报

谈及系统优化,缓存一直是不可或缺的一点。在缓存中间件层面,我们有MemCache,Redis等选择;在系统分层层面,又需要考虑多级缓存;在系统可用性层面,又要考虑到缓存雪崩,缓存穿透,缓存失效等常见的缓存问题...缓存的使用与优化值得我们花费一定的精力去深入理解。《Spring Data Redis》这个系列打算围绕spring-data-redis来进行分析,从hello world到源码分析,夹杂一些不多实战经验(经验有限),不止限于spring-data-redis本身,也会扩展谈及缓存这个大的知识点。

至于为何选择redis,相信不用我赘述,redis如今非常流行,几乎成了项目必备的组件之一。而spring-boot-starter-data-redis模块又为我们在spring集成的项目中提供了开箱即用的功能,更加便捷了我们开发。系列的第一篇便是简单介绍下整个组件最常用的一个工具类:RedisTemplate。

1 引入依赖

代码语言:javascript
复制
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.7.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

springboot的老用户会发现redis依赖名称发生了一点小的变化,在springboot1.4之前,redis依赖的名称为:spring-boot-starter-redis,而在之后较新的版本中,使用spring-boot-starter-redis依赖,则会在项目启动时得到一个过期警告。意味着,我们应该彻底放弃旧的依赖。spring-data这个项目定位为spring提供一个统一的数据仓库接口,如(spring-boot-starter-data-jpa,spring-boot-starter-data-mongo,spring-boot-starter-data-rest),将redis纳入后,改名为了spring-boot-starter-data-redis。

2 配置redis连接

resources/application.yml

代码语言:javascript
复制
spring:
  redis:
    host: 127.0.0.1
    database: 0
    port: 6379
    password:

本机启动一个单点的redis即可,使用redis的0号库作为默认库(默认有16个库),在生产项目中一般会配置redis集群和哨兵保证redis的高可用,同样可以在application.yml中修改,非常方便。

3 编写测试类

代码语言:javascript
复制
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
   @Autowired
   private RedisTemplate redisTemplate;// <1>

   @Test
   public void test() throws Exception {
     redisTemplate.opsForValue().set("student:1", "kirito"); // <2>
     Assertions.assertThat(redisTemplate.opsForValue().get("student:1")).isEqualTo("kirito");
   }
}

<1> 引入了RedisTemplate,这个类是spring-starter-data-redis提供给应用直接访问redis的入口。从其命名就可以看出,其是模板模式在spring中的体现,与restTemplate,jdbcTemplate类似,而springboot为我们做了自动的配置,具体会在下文详解。

<2> redisTemplate通常不直接操作键值,而是通过opsForXxx()访问,在本例中,key和value均为字符串类型。绑定字符串在实际开发中也是最为常用的操作类型。

4 详解RedisTemplate的API

RedisTemplate为我们操作Redis提供了丰富的API,可以将他们简单进行下归类。

4.1 常用数据操作

这一类API也是我们最常用的一类。

众所周知,redis存在5种数据类型:

字符串类型(string),散列类型(hash),列表类型(list),集合类型(set),有序集合类型(zset)

而redisTemplate实现了RedisOperations接口,在其中,定义了一系列与redis相关的基础数据操作接口,数据类型分别于下来API对应:

代码语言:javascript
复制
//非绑定key操作
ValueOperations<K, V> opsForValue();
<HK, HV> HashOperations<K, HK, HV> opsForHash();
ListOperations<K, V> opsForList();
SetOperations<K, V> opsForSet();
ZSetOperations<K, V> opsForZSet();
//绑定key操作
BoundValueOperations<K, V> boundValueOps(K key);
<HK, HV> BoundHashOperations<K, HK, HV> boundHashOps(K key);
BoundListOperations<K, V> boundListOps(K key);
BoundSetOperations<K, V> boundSetOps(K key);
BoundZSetOperations<K, V> boundZSetOps(K key);

若以bound开头,则意味着在操作之初就会绑定一个key,后续的所有操作便默认认为是对该key的操作,算是一个小优化。

4.2 对原生Redis指令的支持

Redis原生指令中便提供了一些很有用的操作,如设置key的过期时间,判断key是否存在等等...

常用的API列举:

RedisTemplate API

原生Redis指令

说明

public void delete(K key)

DEL key [key ...]

删除给定的一个或多个 key

public Boolean hasKey(K key)

EXISTS key

检查给定 key 是否存在

public Boolean expire/expireAt(...)

EXPIRE key seconds

为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。

public Long getExpire(K key)

TTL key

以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。

更多的原生Redis指令支持可以参考javadoc

4.3 CAS操作

CAS(Compare and Swap)通常有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。CAS也通常与并发,乐观锁,非阻塞,机器指令等关键词放到一起讲解。可能会有很多朋友在秒杀场景的架构设计中见到了Redis,本质上便是利用了Redis分布式共享内存的特性以及一系列的CAS指令。还记得在4.1中通过redisTemplate.opsForValue()或者redisTemplate.boundValueOps()可以得到一个ValueOperations或BoundValueOperations接口(以值为字符串的操作接口为例),这些接口除了提供了基础操作外,还提供了一系列CAS操作,也可以放到RedisTemplate中一起理解。

常用的API列举:

ValueOperations API

原生Redis指令

说明

Boolean setIfAbsent(K key, V value)

SETNX key value

将 key 的值设为 value ,当且仅当 key 不存在。设置成功,返回 1 , 设置失败,返回 0 。

V getAndSet(K key, V value)

GETSET key value

将给定 key 的值设为 value ,并返回 key 的旧值(old value)。

Long increment(K key, long delta)/Double increment(K key, double delta)

INCR/INCRBY/INCRBYFLOAT

将 key 所储存的值加上增量 increment 。 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行INCR/INCRBY/INCRBYFLOAT命令。线程安全的+

关于CAS的理解可以参考我之前的文章java并发实践--CAS或者其他博文。

4.4 发布订阅

redis之所以被冠以银弹,万金油的称号,关键在于其实现的功能真是太多了,甚至实现了一部分中间件队列的功能,其内置的channel机制,可以用于实现分布式的队列和广播。

RedisTemplate提供了convertAndSend()功能,用于发送消息,与RedisMessageListenerContainer 配合接收,便实现了一个简易的发布订阅。如果想要使用Redis实现发布订阅,可以参考我之前的文章。浅析分布式下的事件驱动机制

4.5 Lua脚本

RedisTemplate中包含了这样一个Lua执行器,意味着我们可以使用RedisTemplate执行Lua脚本。

代码语言:javascript
复制
private ScriptExecutor<K> scriptExecutor;

Lua这门语言也非常有意思,小巧而精悍,有兴趣的朋友可以去了解一下nginx+lua开发,使用openResty框架。而Redis内置了Lua的解析器,由于Redis单线程的特性(不严谨),可以使用Lua脚本,完成一些线程安全的符合操作(CAS操作仅仅只能保证单个操作的线程安全,无法保证复合操作,如果你有这样的需求,可以考虑使用Redis+Lua脚本)。

代码语言:javascript
复制
public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) {
   return scriptExecutor.execute(script, keys, args);
}

上述操作便可以完成对Lua脚本的调用。这儿有一个简单的示例,使用Redis+Lua脚本实现分布式的应用限流。分布式限流

5 总结

Spring Data Redis系列的第一篇,介绍了spring-data对redis操作的封装,顺带了解redis具备的一系列特性,如果你对redis的理解还仅仅停留在它是一个分布式的key-value数据库,那么相信现在你一定会感叹其竟然如此强大。后续将会对缓存在项目中的应用以及spring-boot-starter-data-redis进一步解析。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-10-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Kirito的技术分享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 引入依赖
  • 2 配置redis连接
  • 3 编写测试类
  • 4 详解RedisTemplate的API
    • 4.1 常用数据操作
      • 4.2 对原生Redis指令的支持
        • 4.3 CAS操作
          • 4.4 发布订阅
            • 4.5 Lua脚本
              • 5 总结
              相关产品与服务
              云数据库 Redis
              腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档