一般操作Redis,常用的做法是在SpringBoot中注入一个RedisTemplate,利用各种OpsForXXX来使用,利用Json序列化字符串到Redis当中
问题
用RedisTemplate的问题有 无法避免大Key的问题,以及需要自行组织key的命名规则
SpringDataRedis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
实体类配置
只需要在实体类上加一个RedisHash注解,指定存储的key前缀,然后在定义为id的字段上加上@Id即可 这里的@Id注解和Jpa的@Id作用差不多 但是不是同一个类
- 这里的@Id注解是
spingframework.data.annotation
包下的 - 而Jpa中的@Id注解
karta.persist
包下的
所以需要存储到Redis的实体类例子如下:
@Data
@AllArgsConstructor
@NoArgsConstructor
@RedisHash(RedisKeyPrefix.UNIT_CONNECT_STATUS)
@Builder
@FieldNameConstants
public class UnitConnectStatus implements Serializable {
@Id
private Integer unitId;
private Integer unitType;
private Boolean server2gateway;
private Boolean gateway2unit;
}
创建Repo接口操作Redis数据
public interface ConnectRepo extends CrudRepository<UnitConnectStatus,Integer> {
void updateServer2GatewayByUnitId(Boolean data,Integer unitId);
void updateGateway2UnitByUnitId(Boolean data,Integer unitId);
}
只需要继承了CrudRepository 就可以像Jpa一样操作Redis的数据,在Redis中 CrudRepository用Hash格式来存储数据如下
Tips
使用这种方法操作Redis有几个点需要注意
-
repo.save操作不是原子的,如果频繁调用save方法的同时进行查询,有很大的概率会查询到空值,原因是save方法的逻辑是先删除再save,因此需要更新实体类的部分属性的时候尽量不用save操作,而是使用
RedisKeyValueTemplate的update
方法进行部分更新,部分更新的例子如下:新定义一个update的repo,对于需要更新不同类型的数据,可以重载方法
@Component public class EscStatusUpdateRepo { private final RedisKeyValueTemplate redisKeyValueTemplate; @Autowired public EscStatusUpdateRepo(RedisKeyValueTemplate redisKeyValueTemplate) { this.redisKeyValueTemplate=redisKeyValueTemplate; } @Async public void updateEntry(String fieldName,Integer unitId, Boolean data) { Assert.notNull(unitId,"unitId is null"); Assert.notNull(data,"fault is empty"); redisKeyValueTemplate.update(new PartialUpdate<>(unitId,EscalatorStatus.class) .set(fieldName,data) ); } }
-
repo接口不支持像Jpa那样通过方法名解析特定的查询逻辑,例如在Jpa中我们可以通过定义一个接口的方法
findByNameAndAge(String name,Integer age)
来以name和age条件查询实体数据,这在Redis当中是不支持的