14.1)简介:
redis是一款高性能的NOSQL系列的非关系型数据库
14.1.1)非关系型数据库的优势:
1)性能NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。
2)可扩展性同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。
14.1.2) 关系型数据库的优势:
1)复杂查询可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。
2)事务支持使得对于安全性能很高的数据访问要求得以实现。对于这两类数据库,对方的优势就是自己的弱势,反之亦然。
14.1.3) 总结
关系型数据库与NoSQL数据库并非对立而是互补的关系,即通常情况下使用关系型数据库,在适合使用NoSQL的时候使用NoSQL数据库,
让NoSQL数据库对关系型数据库的不足进行弥补。
一般会将数据存储在关系型数据库中,在nosql数据库中备份存储关系型数据库的数据
14.2)使用场景
•缓存(数据查询、短连接、新闻内容、商品内容等等)
• 聊天室的在线好友列表
• 任务队列。(秒杀、抢购、12306等等)
• 应用排行榜
• 网站访问统计
• 数据过期处理(可以精确到毫秒
• 分布式集群架构中的session分离
14.3)安装Redis
14.3.1)Windows下载安装
官网:https://redis.io
中文网:http://www.redis.net.cn/ (https://github.com/microsoftarchive/redis/releases/tag/win-3.2.100)
下载解压后直接可以使用:
- redis.windows.conf:配置文件
- redis-cli.exe:redis的客户端
- redis-server.exe:redis服务器端
14.3.1) Linux下载安装
1.安装 gcc 编译
因为后面安装redis的时候需要编译,所以事先得先安装gcc编译。阿里云主机已经默认安装了 gcc,如
果是自己安装的虚拟机,那么需要先安装一下 gcc:
yum install gcc-c++
2.下载 redis
有两种方式下载安装包,一种是去官网上下载(https://redis.io),然后将安装包考到 centos 中,另 种方法是直接使用 wget 来下载:
wget http://download.redis.io/releases/redis-3.2.8.tar.gz
如果没有安装过 wget,可以通过如下命令安装:
yum install wget
3.解压安装
解压安装包:
tar –vzxf redis-3.2.8.tar.gz
然后将解压的文件夹 redis-3.2.8 放到 /software下,software文件夹是自己在根目录下创建的,然后 进入 /software/redis-3.2.8/ 文件夹下,执行 make 命令即可完成安装。
【注】如果 make 失败,可以尝试如下命令:
make MALLOC=libc
make install
4.修改配置文件
安装成功之后,需要修改一下配置文件,包括允许接入的 ip,允许后台执行,设置密码等等。 打开 redis 配置文件:
vi redis.conf
在命令模式下输入 /bind 来查找 bind 配置,按 n 来查找下一个,找到配置后,将 bind 配置成
0.0.0.0,允许任意服务器来访问 redis,即:
bind 0.0.0.0
使用同样的方法,将 daemonize 改成 yes (默认为 no),允许 redis 在后台执行。
将 requirepass 注释打开,并设置密码为 123456(密码自己设置)。
5.启动 redis
在 redis-3.2.8 目录下,指定刚刚修改好的配置文件 redis.conf 来启动 redis:
redis-server ./redis.conf
由于我们设置了密码,在启动客户端之后,必须输入 auth root(设置的密码) 才可登录进入客户端。
[root@VM_0_16_centos src]# redis-cli
127.0.0.1:6379> get test
(error) NOAUTH Authentication required.
127.0.0.1:6379> AUTH root
OK
127.0.0.1:6379> get test
"1"
Linux下redis运维的一些指令:
redis 的启动、关闭 判断其是否在运行中
#检查后台进程是否正在运行
ps -ef |grep redis
ps aux | grep redis
#检测6379端口是否在监听
netstat -lntp | grep 6379
#使用配置文件启动redis服务
./redis-server /etc/redis/redis.conf
#使用`redis-cli`客户端检测连接是否正常
./redis-cli -h 127.0.0.1 -p 6379 (登陆客户端)
#关闭redis:
redis-cli shutdown
14.4)集成redis
14.4.1)依赖导入
用于业务中将对象转换为json格式的字符串;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--springboot 2.x 使用的Lettuce 依赖org.apache.commons-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--阿里巴巴fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.35</version>
</dependency>
14.4.2)yaml配置文件
#redis相关配置
redis:
# 配置redis的主机地址,需要修改成自己的
host: xxx
port: 6379
password: xxx
database: 5
timeout: 5000
lettuce:
pool:
# 连接池中的最大空闲连接,默认值也是8。
max-idle: 50
# 连接池中的最小空闲连接,默认值也是0。
min-idle: 0
# 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool 的状态为exhausted(耗尽)
max-active: 50
# 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接 抛出JedisConnectionException
max-wait: 1
redis 配置类:
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.Arrays;
@Configuration
public class RedisConfiguration extends CachingConfigurerSupport {
@Resource
private LettuceConnectionFactory lettuceConnectionFactory;
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(lettuceConnectionFactory);
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
template.setConnectionFactory(lettuceConnectionFactory);
//key序列化方式
template.setKeySerializer(redisSerializer);
//value序列化
template.setValueSerializer(serializer);
//value hashmap序列化
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
@Bean("myKeyGenerator")
@Override
public KeyGenerator keyGenerator() {
return (Object target, Method method, Object... objects) -> method.getName() + "(" + Arrays.toString(objects) + ")";
}
@Bean
public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(lettuceConnectionFactory);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(3))//只有通过注解的方式设置缓存才生效
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()))
.disableCachingNullValues();
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
}
14.5)常用 api 介绍
Redis提供了StringRedisTemplate和RedisTemplate两种模板,后者需要进行序列化比较麻烦,所以本文选择StringRedisTemplate;
14.5.1) redis:string 类型
新建一个 RedisServiceImpl,注入 StringRedisTemplate,使用 stringRedisTemplate.opsForValue() 可以获取 ValueOperations<String, String> 对象,通过该对象即可读写 redis 数据库了。
应为存放的是String类型所以可以存放图片,文档,等一切形式的文件;
@Service
public class RedisServiceImpl {
@Resource
private StringRedisTemplate stringRedisTemplate;
public void setString(String key, String value) {
ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
valueOperations.set(key,value);
}
public String GetString(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
测试类
value也可以为对象,只要最后以json格式存进去即可;
@Resource
RedisServiceImpl redisService;
@Test
public void testString() {
String key="lisi";
String value="第一名";
redisService.setString(key,value);
System.out.println(redisService.GetString(key));
}
14.5.2)redis:hash 类型
hash 类型其实原理和 string 一样的,但是有两个 key,使用 stringRedisTemplate.opsForHash() 可以获取 HashOperations<String, Object, Object> 对象。比如我们要存储订单信息,所有订单 信息都放在 order 下,针对不同用户的订单实体,可以通过用户的 id 来区分,这就相当于两个 key 了。
public void setHash(String key,String filedKey,String value){
stringRedisTemplate.opsForHash().put(key,filedKey,value);
}
public String getHash(String key,String filedKey){
return (String) stringRedisTemplate.opsForHash().get(key,filedKey);
}
测试类
将对象以json格式存入Redis中;
@Test
public void testHash() {
String key="userId";
String userId="1";
UserPO po=new UserPO();
po.setAge(12);
po.setName("lisi");
redisService.setHash(key,userId, JSON.toJSONString(po));
System.out.println(redisService.getHash(key,userId));
}
结果
{"age":12,"name":"lisi"}
以java对象的形式取出json格式的对象
UserPO po1 = JSON.parseObject(redisService.getHash(key,userId),UserPO.class);
@Test
public void testHash() {
String key="userId";
String userId="1";
UserPO po=new UserPO();
po.setAge(12);
po.setName("lisi");
redisService.setHash(key,userId, JSON.toJSONString(po));
UserPO po1 = JSON.parseObject(redisService.getHash(key,userId),UserPO.class);
System.out.println("po1:"+po1);
}
结果
po1:UserPO{age=12, name='lisi', son=null}
14.5.3) redis:list 类型
list 类型左右两边都可以进行添加,可以用来模拟消息队列;
**stringRedisTemplate.opsForList().range(key,start,end)**是获取对应key的start到end下标的所有者,当start为0,end为-1时表示对应key的所有值
public void leftPushList(String key, String value) {
stringRedisTemplate.opsForList().leftPush(key,value);
}
public String rightPopList(String key) {
return stringRedisTemplate.opsForList().rightPop(key);
}
public List<String> getRange(String key, int start, int end) {
return stringRedisTemplate.opsForList().range(key,start,end);
}
测试
@Test
public void TestList() {
String key="lisi";
// redisService.leftPushList(key,"1");
// redisService.leftPushList(key,"2");
// redisService.leftPushList(key,"3");
System.out.println(redisService.rightPopList(key));
System.out.println("all:"+redisService.getRange(key,0,-1));
}