一、Redis简介
Redis是开源的内存数据结构存储系统,可用作数据库、缓存和消息队列。
特点:
- 高性能:基于内存操作
- 丰富数据类型:String、List、Set、Hash、ZSet等
- 持久化:RDB和AOF
- 高可用:主从复制、哨兵、集群
二、SpringBoot整合Redis
添加依赖
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
|
配置连接
1 2 3 4 5 6 7 8 9 10 11 12
| spring: redis: host: localhost port: 6379 password: database: 0 timeout: 3000 lettuce: pool: max-active: 8 max-idle: 8 min-idle: 0
|
配置RedisTemplate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Configuration public class RedisConfig {
@Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(serializer); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; } }
|
三、String操作
基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Autowired private RedisTemplate<String, Object> redisTemplate;
redisTemplate.opsForValue().set("key", "value");
redisTemplate.opsForValue().set("key", "value", 1, TimeUnit.HOURS);
redisTemplate.opsForValue().setIfAbsent("key", "value");
Object value = redisTemplate.opsForValue().get("key");
redisTemplate.delete("key");
Boolean exists = redisTemplate.hasKey("key");
redisTemplate.expire("key", 1, TimeUnit.HOURS);
|
计数器
1 2 3 4 5 6
| Long increment = redisTemplate.opsForValue().increment("counter"); Long increment = redisTemplate.opsForValue().increment("counter", 10);
Long decrement = redisTemplate.opsForValue().decrement("counter");
|
四、Hash操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| redisTemplate.opsForHash().put("user:1", "name", "张三"); redisTemplate.opsForHash().put("user:1", "age", "20");
Map<String, Object> map = new HashMap<>(); map.put("name", "李四"); map.put("age", "25"); redisTemplate.opsForHash().putAll("user:2", map);
Object name = redisTemplate.opsForHash().get("user:1", "name");
Map<Object, Object> user = redisTemplate.opsForHash().entries("user:1");
redisTemplate.opsForHash().delete("user:1", "name");
redisTemplate.opsForHash().increment("user:1", "age", 1);
Boolean exists = redisTemplate.opsForHash().hasKey("user:1", "name");
|
五、List操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| redisTemplate.opsForList().leftPush("list", "value1"); redisTemplate.opsForList().leftPushAll("list", "value2", "value3");
redisTemplate.opsForList().rightPush("list", "value4");
List<Object> list = redisTemplate.opsForList().range("list", 0, -1);
Object value = redisTemplate.opsForList().leftPop("list");
Object value = redisTemplate.opsForList().rightPop("list");
Long size = redisTemplate.opsForList().size("list");
Object value = redisTemplate.opsForList().index("list", 0);
redisTemplate.opsForList().set("list", 0, "newValue");
|
六、Set操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| redisTemplate.opsForSet().add("set", "value1", "value2");
Set<Object> set = redisTemplate.opsForSet().members("set");
redisTemplate.opsForSet().remove("set", "value1");
Boolean exists = redisTemplate.opsForSet().isMember("set", "value1");
Long size = redisTemplate.opsForSet().size("set");
Object value = redisTemplate.opsForSet().randomMember("set");
Set<Object> intersect = redisTemplate.opsForSet().intersect("set1", "set2");
Set<Object> union = redisTemplate.opsForSet().union("set1", "set2");
|
七、ZSet操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| redisTemplate.opsForZSet().add("zset", "value1", 100); redisTemplate.opsForZSet().add("zset", "value2", 200);
Set<Object> set = redisTemplate.opsForZSet().range("zset", 0, -1);
Set<Object> set = redisTemplate.opsForZSet().rangeByScore("zset", 0, 200);
Long rank = redisTemplate.opsForZSet().rank("zset", "value1");
Double score = redisTemplate.opsForZSet().score("zset", "value1");
redisTemplate.opsForZSet().incrementScore("zset", "value1", 10);
redisTemplate.opsForZSet().remove("zset", "value1");
redisTemplate.opsForZSet().removeRange("zset", 0, 10);
|
八、缓存注解
启用缓存
1 2 3 4 5 6 7
| @EnableCaching @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
|
@Cacheable
查询时使用缓存
1 2 3 4
| @Cacheable(value = "user", key = "#id") public User getUserById(Long id) { return userMapper.selectById(id); }
|
@CachePut
更新缓存
1 2 3 4 5
| @CachePut(value = "user", key = "#user.id") public User updateUser(User user) { userMapper.updateById(user); return user; }
|
@CacheEvict
删除缓存
1 2 3 4
| @CacheEvict(value = "user", key = "#id") public void deleteUser(Long id) { userMapper.deleteById(id); }
|
九、分布式锁
使用SETNX实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public boolean tryLock(String key, String value, long expireTime) { Boolean result = redisTemplate.opsForValue() .setIfAbsent(key, value, expireTime, TimeUnit.SECONDS); return result != null && result; }
public void unlock(String key, String value) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " + " return redis.call('del', KEYS[1]) " + "else " + " return 0 " + "end"; redisTemplate.execute( new DefaultRedisScript<>(script, Long.class), Collections.singletonList(key), value ); }
|
使用Redisson
1 2 3 4
| <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12
| @Autowired private RedissonClient redissonClient;
public void doSomething() { RLock lock = redissonClient.getLock("myLock"); try { lock.lock(); } finally { lock.unlock(); } }
|
十、最佳实践
Key命名规范
1 2 3
| String key = "user:info:1001"; String key = "order:detail:2001";
|
序列化选择
- Key:StringRedisSerializer
- Value:Jackson2JsonRedisSerializer
过期时间
1 2
| redisTemplate.opsForValue().set("key", "value", 1, TimeUnit.HOURS);
|
批量操作
1 2 3 4 5 6 7 8 9
| redisTemplate.executePipelined(new SessionCallback<Object>() { @Override public Object execute(RedisOperations operations) { operations.opsForValue().set("key1", "value1"); operations.opsForValue().set("key2", "value2"); return null; } });
|
十一、总结
SpringBoot整合Redis要点:
- 配置RedisTemplate和序列化器
- 熟练使用各数据类型操作
- 合理使用缓存注解
- 分布式锁保证并发安全
- 遵循最佳实践规范