还在只用RedisTemplate访问Redis吗? 下

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 还在只用RedisTemplate访问Redis吗? 下

JPA Repository

我们知道使用JPA Repository来访问DataBase的时候,增删改查那样的操作能够很方便的实现,基本就是定义个接口,代码都不用写,Spring就帮我们完成了大部分的工作,那么访问Redis是不是也可以这样呢?答案是肯定的,我们来看代码 首先我们还是定义一个POJO

@RedisHash(value = "cache-book", timeToLive = 600)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CacheBook implements Serializable {
    @Id
    private Long userId;
    @Indexed
    private String name;
    private String author;
}

这个类与我们上面template上面的类的区别就是我们加了两个注解, 在类开头加了 @RedisHash(value = "cache-book", timeToLive = 600) 在字段上面加了@Id@Indexed 定义一个Repository的接口

public interface CacheBookRepository extends CrudRepository<CacheBook, Long> {
    Optional<CacheBook> findOneByName(String name);
}

再定义一个service和上面那个例子template一样,缓存中有就到缓存中拿,没有就到持久化存储中找,并写入缓存

@Slf4j
@Service
public class BookService {
    private static final String CACHE = "repository-book";
    @Autowired
    private CacheBookRepository cacheRepository;
    @Autowired
    private BookRepository bookRepository;
    public Optional<CacheBook> findOneBook(String name) {
        Optional<CacheBook> optionalCacheBook = cacheRepository.findOneByName(name);
        if(!optionalCacheBook.isPresent())
        {
            Optional<CacheBook> book = bookRepository.getBook(name);
            log.info("Book Found: {}", book);
            if (book.isPresent()) {
                log.info("Put book {} to Redis.", name);
                cacheRepository.save(book.get());
            }
            return book;
        }
        return optionalCacheBook;
    }
}

代码很简单,简单到不敢相信是真的。还是一样,调用这个方法,我们来看存在Redis里面的数据

127.0.0.1:6379> keys *
1) "repository-book:2"
2) "repository-book:2:idx"
3) "repository-book"
4) "repository-book:name:apache kafka"
5) "repository-book:name:python"
6) "repository-book:1:idx"
7) "repository-book:1"

哇,感觉存的内容有些多, 不用怕我们来看下各自存什么数据 首先看最短的一个

127.0.0.1:6379> smembers repository-book
1) "1"
2) "2"

它里面存的是我们的id所有的value,可以用来判断id是否存在 再来看

127.0.0.1:6379> hgetall repository-book:2
1) "_class"
2) "com.ken.redisrepositorysample.model.CacheBook"
3) "author"
4) "lisi"
5) "name"
6) "python"
7) "userId"
8) "2"

这个是我们数据存放的地方

127.0.0.1:6379> smembers repository-book:1:idx
1) "repository-book:name:apache kafka"
127.0.0.1:6379> smembers "repository-book:name:apache kafka"
1) "1"

另外两个都是set, 存在在它们里面的数据是索引信息。由此可以看出通过JPA Repository 的方式,代码很少,而且存储的数据也很通用,个人觉得是比较理想的访问方法。

Cache

我们已经看了两种方式,在访问的时候遵循这样的模式:缓存中有就从缓存中返回,没有就从持久化存储中找,然后写入缓存,这部分代码我也不想自己写,那么Cache就是你的救星。

我们先看代码 我们这次使用内存数据库H2作为持久化存储, 放一个schema.sql在resouces下面

drop table t_book if exists;
create table t_book (
    id bigint auto_increment,
    create_time timestamp,
    update_time timestamp,
    name varchar(255),
    author varchar(200),
    primary key (id)
);
insert into t_book (name, author, create_time, update_time) values ('python', 'zhangsan', now(), now());
insert into t_book (name, author, create_time, update_time) values ('hadoop', 'lisi', now(), now());
insert into t_book (name, author, create_time, update_time) values ('java', 'wangwu', now(), now());

然后定义POJO

@Entity
@Table(name = "T_BOOK")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CacheBook implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String author;
    @Column(updatable = false)
    @CreationTimestamp
    private Date createTime;
    @UpdateTimestamp
    private Date updateTime;
}

完全是和数据库绑定的代码,和缓存没有任何关系 一个Repository来访问数据库

public interface BookRepository extends JpaRepository<CacheBook, Long> {
}

定义一个service来调用它

@Slf4j
@Service
@CacheConfig(cacheNames = "cache-book")
public class BookService {
    @Autowired
    private BookRepository bookRepository;
    @Cacheable
    public List<CacheBook> findAllCoffee() {
        return bookRepository.findAll();
    }
    @CacheEvict
    public void reloadCoffee() {
    }
}

这里就比较关键了,在类上加上了注解 @CacheConfig(cacheNames = "cache-book") 在方法上面加上了Cacheable和CacheEvict, Cacheable这个方法就是用来实现逻辑,有就从缓存中拿,没有就从数据库拿的,CacheEvict是调用这个方法的时候清除缓存。

然后再启动入口程序的地方加上注解 @EnableJpaRepositories @EnableCaching(proxyTargetClass = true) 在配置文件application.properties中加上

spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
management.endpoints.web.exposure.include=*
spring.cache.type=redis
spring.cache.cache-names=cache-book
spring.cache.redis.time-to-live=600000
spring.cache.redis.cache-null-values=false
spring.redis.host=localhost

这样就可以了, 感觉就是通过配置下就把缓存给完成了,非常的简单 我们来看Redis中是怎么存的

127.0.0.1:6379> keys *
1) "cache-book::SimpleKey []"
127.0.0.1:6379> get "cache-book::SimpleKey []"
"\xac\xed\x00\x05sr\x00\x13java.util.ArrayListx\x81\xd2\x1d\x99\xc7a\x9d\x03\x00\x01I\x00\x04sizexp\x00\x00\x00\x03w\x04\x00\x00\x00\x03sr\x00(com.ken.rediscachesample.model.CacheBook\xec\xcbR=\xe1U\x9b\xf7\x02\x00\x05L\x00\x06authort\x00\x12Ljava/lang/String;L\x00\ncreateTimet\x00\x10Ljava/util/Date;L\x00\x02idt\x00\x10Ljava/lang/Long;L\x00\x04nameq\x00~\x00\x03L\x00\nupdateTimeq\x00~\x00\x04xpt\x00\bzhangsansr\x00\x12java.sql.Timestamp&\x18\xd5\xc8\x01S\xbfe\x02\x00\x01I\x00\x05nanosxr\x00\x0ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\b\x00\x00\x01\x84\xff]\x85\xb0x\b-\x81\x80sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x00\x00\x00\x00\x01t\x00\x06pythonsq\x00~\x00\bw\b\x00\x00\x01\x84\xff]\x85\xb0x\b-\x81\x80sq\x00~\x00\x02t\x00\x04lisisq\x00~\x00\bw\b\x00\x00\x01\x84\xff]\x85\xb0x\b<\xbf\xd8sq\x00~\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x02t\x00\x06hadoopsq\x00~\x00\bw\b\x00\x00\x01\x84\xff]\x85\xb0x\b<\xbf\xd8sq\x00~\x00\x02t\x00\x06wangwusq\x00~\x00\bw\b\x00\x00\x01\x84\xff]\x85\xb0x\b<\xbf\xd8sq\x00~\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x03t\x00\x04javasq\x00~\x00\bw\b\x00\x00\x01\x84\xff]\x85\xb0x\b<\xbf\xd8x"

看到没有,就是当成Redis里面的String来存的, 如果数据量比较小,那是非常的方便,如果数据量大,这种方式就有些问题了。

总结

我们看了这三种方式,这里仅仅是做了个入门,每个里面都有很多细节的地方需要去研究和使用,整体的感觉是要想使用的简单,那么存储在Redis中的数据就要量少,量大后,就需要自己来定制了,那基本上要用RedisTemplate来做一些工作。



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3月前
|
缓存 NoSQL Java
RedisTemplate操作Redis,这一篇文章就够了
redis是一款开源的Key-Value数据库,运行在内存中,由C语言编写。企业开发通常采用Redis来实现缓存。同类的产品还有memcache 、memcached 等。
243 1
|
24天前
|
NoSQL 安全 网络安全
Redis连接:加速数据访问与保障安全传输的关键
Redis连接:加速数据访问与保障安全传输的关键
|
1月前
|
存储 JSON NoSQL
[Redis]——RedisTemplate的两种序列化方式
[Redis]——RedisTemplate的两种序列化方式
|
2月前
|
缓存 NoSQL Java
一次访问Redis延时高问题排查与总结
作者抽丝剥茧的记录了一次访问Redis延时高问题的排查和总结。
421 1
|
5月前
|
NoSQL Redis
RedisTemplate执行lua脚本在Redis集群模式下报错EvalSha is not supported in cluster environment.
RedisTemplate执行lua脚本在Redis集群模式下报错EvalSha is not supported in cluster environment.
161 0
|
5月前
|
NoSQL Redis
redisTemplate+redis+lua解决redis分布式锁集群报错问题
redisTemplate+redis+lua解决redis分布式锁集群报错问题
|
6月前
|
NoSQL Redis
【Redis】自定义RedisTemplate模板,拿来直接使用
【Redis】自定义RedisTemplate模板,拿来直接使用
39 0
|
7月前
|
缓存 NoSQL 关系型数据库
课时3:通过缓存来加速数据库访问(MySQL+Redis)
课时3:通过缓存来加速数据库访问(MySQL+Redis)
153 0
|
8月前
|
NoSQL Redis Docker
访问redis集群提示连接超时的问题
访问redis集群提示连接超时的问题
176 0
|
9月前
|
监控 NoSQL Java
记一次应用访问Redis超时的案例分析
记一次应用访问Redis超时的案例分析
220 2

热门文章

最新文章