Redis入门
-
Redis是一款基于键值对的NoSQL数据库,它的值支持多种数据结构:
字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。
-
Redis将所有的数据都存放在内存中,所以它的读写性能十分惊人。
同时,Redis还可以将内存中的数据以快照或日志的形式保存到硬盘上,以保证数据的安全性。
-
Redis典型的应用场景包括:缓存、排行榜、计数器、社交网络、消息队列等。
示例:
Spring整合Redis
引入依赖
spring-boot-starter-data-redis
配置Redis
- 配置数据库参数
- 编写配置类,构造RedisTemplate
访问Redis
- redisTemplate.opsForValue()
- redisTemplate.opsForHash()
- redisTemplate.opsForList()
- redisTemplate.opsForSet()
- redisTemplate.opsForZSet()
1.导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
2.配置
- 配置数据库参数 application.properties
spring.redis.database = 1; //Redis默认有16个数据库,选择第1个数据库
spring.redis.host=localhost; //ip地址
spring.redis.port=6379; //端口号
- 配置RedisConfig:因为默认spring对于spring的配置中, RedisTemplate<Object,Object>,但是我们一般习惯使用RedisTemplate<String,Object>,利用String作为key。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String,Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
//设置key的序列化方式
template.setKeySerializer(RedisSerializer.string());
//设置value的序列化方式
template.setValueSerializer(RedisSerializer.json());
//设置hash的key序列化方式
template.setHashKeySerializer(RedisSerializer.string());
//设置hash的value的序列化方式
template.setHashValueSerializer(RedisSerializer.json());
template.afterPropertiesSet();
return template;
}
}
3.访问Redis
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class RedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testStrings() {
String redisKey = "test:count";
redisTemplate.opsForValue().set(redisKey, 1);
System.out.println(redisTemplate.opsForValue().get(redisKey)); // 1
System.out.println(redisTemplate.opsForValue().increment(redisKey)); // 2
System.out.println(redisTemplate.opsForValue().decrement(redisKey)); // 1
}
@Test
public void testHashes() {
String redisKey = "test:user";
redisTemplate.opsForHash().put(redisKey, "id", 1);
redisTemplate.opsForHash().put(redisKey, "username", "zhangsan");
System.out.println(redisTemplate.opsForHash().get(redisKey, "id")); // 1
System.out.println(redisTemplate.opsForHash().get(redisKey, "username")); // zhangsan
}
@Test
public void testLists() {
String redisKey = "test:ids";
redisTemplate.opsForList().leftPush(redisKey, 101);
redisTemplate.opsForList().leftPush(redisKey, 102);
redisTemplate.opsForList().leftPush(redisKey, 103);
System.out.println(redisTemplate.opsForList().size(redisKey)); // 3
System.out.println(redisTemplate.opsForList().index(redisKey, 0)); // 103
System.out.println(redisTemplate.opsForList().range(redisKey, 0, 2)); // 103 102 101
System.out.println(redisTemplate.opsForList().leftPop(redisKey)); // 103
System.out.println(redisTemplate.opsForList().leftPop(redisKey)); // 102
System.out.println(redisTemplate.opsForList().leftPop(redisKey)); // 101
}
@Test
public void testSets() {
String redisKey = "test:teachers";
redisTemplate.opsForSet().add(redisKey, "刘备", "关羽", "张飞", "赵云", "诸葛亮");
System.out.println(redisTemplate.opsForSet().size(redisKey)); // 5
System.out.println(redisTemplate.opsForSet().pop(redisKey)); // 随机弹出一个
System.out.println(redisTemplate.opsForSet().members(redisKey));
}
@Test
public void testSortedSets() {
String redisKey = "test:students";
redisTemplate.opsForZSet().add(redisKey, "唐僧", 80);
redisTemplate.opsForZSet().add(redisKey, "悟空", 90);
redisTemplate.opsForZSet().add(redisKey, "八戒", 50);
redisTemplate.opsForZSet().add(redisKey, "沙僧", 70);
redisTemplate.opsForZSet().add(redisKey, "白龙马", 60);
System.out.println(redisTemplate.opsForZSet().zCard(redisKey)); // 5
System.out.println(redisTemplate.opsForZSet().score(redisKey, "八戒")); // 50
System.out.println(redisTemplate.opsForZSet().Rank(redisKey, "八戒")); // 排名索引 1
System.out.println(redisTemplate.opsForZSet().reverseRank(redisKey, "八戒")); // 倒序索引 4
System.out.println(redisTemplate.opsForZSet().reverseRange(redisKey, 0, 2));
}
@Test
public void testKeys() {
redisTemplate.delete("test:user"); // 删除key
System.out.println(redisTemplate.hasKey("test:user")); // 判断key是否存在
redisTemplate.expire("test:students", 10, TimeUnit.SECONDS); // 过期时间
}
// 多次访问同一个key 可以通过Bound***Operations对key进行绑定,在操作就无需传入key
@Test
public void testBoundOperations() {
String redisKey = "test:count";
BoundValueOperations operations = redisTemplate.boundValueOps(redisKey);
operations.increment();
operations.increment();
operations.increment();
System.out.println(operations.get());
}
// redis虽然支持事务,但是并不满足全部的ACID
// 开始事务后,它是将命令依次存在队列中,等到事务开始执行时,会一起执行队列中的命令。因此,命令并不会立即得到结果
// 声明式事务作用于整个方法,方法中需要查询时就不合适了,所以演示编程式事务
// 编程式事务
@Test
public void testTransactional() {
Object obj = redisTemplate.execute(new SessionCallback() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
String redisKey = "test:tx";
//开启事务
operations.multi();
operations.opsForSet().add(redisKey, "zhangsan");
operations.opsForSet().add(redisKey, "lisi");
operations.opsForSet().add(redisKey, "wangwu");
//显示为[],所以一定不要在redis事务中做查询。
System.out.println(operations.opsForSet().members(redisKey));
//提交事务
return operations.exec();
}
});
//这里会显示所有的操作结果
System.out.println(obj);
}
}