1.关于Redis
目前Web项目架构中,Tomcat服务器和数据库分别独立部署,一般可以解决用户量水平一般的绝大多数需求和应用场景。但是伴随着用户数的增长,并发读写数据库增多,会加大数据库访问压力,每一次的读写查询,都需要经过数据库的审查SQL语句等环节,导致性能的大幅下降,严重时直接导致系统宕机。我们急需要一个能够处理反复高频的热门数据的简单存储机构,它不用像关系型数据库那么大的体量,只需要把部分热门数据拦截在操作数据库之前。Redis就是这样一款缓存数据的分布式数据库。
Redis是一款内存使用了类似Java Map (key-value)形式的Nosql 非关系型数据库。Redis(Remote Dictionary Server )即远程字典服务,是 C 语言开发的一个开源的key/value存储系统(官网:http://redis.io),是一个分布式缓存数据库。由于它是基于内存的所以它要比基于硬盘读写的数据库效率更快。家用PC中读取几百万条数据的用时只需要0.1-0.3秒的时间,这个效率非常之高。
2.Redis安装
我们可以去官网,或者各大软件平台中下载Redis安装包,将其安装在电脑中。当已经安装了Redis后,并确保环境变量可用后(这里注意安装过程中可以无需修改任何配置,就会自动配置到环境变量的Path中),可以在命令提示符窗口(CMD)或终端(IDEA的Terminal,或MacOS/Linux的命令窗口)中执行相关命令。
在终端下,可以通过redis-cli
登录Redis客户端:
redis-cli
redis-cli -p 6379
redis-cli -p 6379 -a password #-a后面为password,此操作需要开启redis.conf
文件中的 requirepass选项
在Redis客户端中,可以通过ping
检测Redis是否正常工作,将得到PONG
的反馈:
ping
如上图显示结果,就证明已经成功安装了Redis。
下面可以做几个简单的测试
在Redis客户端中,可以通过set
命令向Redis中存入或修改简单类型的数据:
set name jack
在Redis客户端中,可以通过get
命令从Redis中取出简单类型的数据:
get name
如果使用的Key并不存在,使用
get
命令时,得到的结果将是(nil)
,等效于Java中的null
在Redis客户端中,可以通过keys
命令检索Key:注意:默认情况下,Redis是单线程的,keys
命令会执行整个Redis的检索,所以,执行时间可能较长,可能导致阻塞!
keys *
在Spring Boot项目中读写Redis
首先,需要添加spring-boot-starter-data-redis
依赖项:
<!-- Spring Data Redis:读写Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
以上依赖项默认会连接localhost:6379
,并且无用户名、无密码,所以,当你的Redis符合此配置,则不需要在application.properties
/ application.yml
中添加任何配置就可以直接编程。如果需要显式的配置,各配置项的属性名分别为:
spring.redis.host
spring.redis.port
spring.redis.username
spring.redis.password
在使用以上依赖项实现Redis编程时,需要使用到的工具类型为RedisTemplate
,调用此类的对象的方法,即可实现读写Redis中的数据。
在使用之前,应该先在配置类中使用@Bean
方法创建RedisTemplate
,并实现对RedisTemplate
的基础配置,则在项目的根包下创建config.RedisConfiguration
类:
package cn.tedu.csmall.product.config;
import lombok.extern.slf4j.Slf4j;
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;
import java.io.Serializable;
/**
* Redis的配置类
*
* @author java@tedu.cn
* @version 0.0.1
*/
@Slf4j
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Serializable> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Serializable> redisTemplate
= new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setValueSerializer(RedisSerializer.json());
return redisTemplate;
}
}
3.Redis数据存储操作
基于key/value形式存储数据
127.0.0.1:6379> set test1 123
OK
127.0.0.1:6379> set test2 ab
OK
127.0.0.1:6379> keys *
1) "test1"
2) "test2"
基于key获取redis中存储的数据
127.0.0.1:6379> get test1
"123"
127.0.0.1:6379> get test2
"ab"
127.0.0.1:6379> get test3
(nil)
127.0.0.1:6379>
清除redis中的数据
127.0.0.1:6379> del test1 #test1为key的名字
OK
清除当前数据库数据
127.0.0.1:6379> flushdb
OK
清除所有数据库数据
127.0.0.1:6379> flushall
OK
设置K-V的存储的时间
127.0.0.1:6379> set bomb tnt
OK
127.0.0.1:6379> expire bomb 10
(integer) 1
127.0.0.1:6379> ttl bomb
(integer) 5
127.0.0.1:6379> ttl bomb
(integer) 3
127.0.0.1:6379> ttl bomb
(integer) 3
127.0.0.1:6379> ttl bomb
(integer) 2
127.0.0.1:6379> ttl bomb
(integer) 1
127.0.0.1:6379> ttl bomb
(integer) -2
127.0.0.1:6379> ttl bomb
(integer) -2
127.0.0.1:6379>
上面的TTL是声明周期TIME TO LIVE的意思,我们也可以借助Another-Redis-Desktop-Management——ARDM可视化软件来更好的了解Redis的工作方式。
在Java中我们可以直接调用Redis的API来使用Redis,
@Slf4j
@SpringBootTest
public class RedisTemplateTests {
@Autowired
RedisTemplate<String, Serializable> redisTemplate;
我们自动装配的就是Redis的API,其中Key是字符串类型,而Value可以是任意类型,比如Object,这里我们使用Serializable接口类型来指代实现了这个接口的类型。
@Test
void testValueOpsSet() {
// ValueOperations:用于实现string(Redis)的读写
ValueOperations<String, Serializable> ops = redisTemplate.opsForValue();
// 向Redis中“存入” / “修改”数据
String key = "username";
String value = "admin";
ops.set(key, value);
log.debug("已经向Redis中写入Key={}且Value={}的数据!", key, value);
}
这里调用opsForValue方法所得到的就是一个Value操作对象。
@Test
void testListRightPush() {
List<Brand> brands = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
Brand brand = new Brand();
brand.setId(i + 0L);
brand.setName("测试品牌" + i);
brands.add(brand);
}
ListOperations<String, Serializable> ops = redisTemplate.opsForList();
String key = "brand:list";
for (Brand brand : brands) {
ops.rightPush(key, brand);
}
}
也可以使用opsForList()方法调用List操作对象,也就是我们的K-V键值对中不但可以存单独的Value也可以存储对象的集合。这其中要介绍到的就是缓存中数据的存放形式(也就是栈内存)中的数据进出形式。我们的栈中数据都是以压栈形式存储的。当我们想从左至右依次排列1.2.3.4.5.6.7.8.9.10号数据时,我们必须从右往左依次压入1.2.3.4.5.6.7.8.9.10号数据,这样才能实现这样的排列,也就是上方代码块中的rightPush方法。而当我们往外取数据(弹数据)时,如果调leftPop方法那么1号数据就将被取出。