1、先了解缓存技术:
缓存技术:
什么是缓存?凡是位于速度相差较大的两张硬件或软件之间的,用于协调两者数据传输速度差异的结构,可称之为缓存
缓存的分类
在系统架构的不同层级之间,为了加快数据访问速度,都可以存在缓存里面
1、操作系统磁盘缓存
2、数据库缓存:Query Cache缓存策略、Data Buffer缓存策略
3、应用程序缓存:对象缓存、查询缓存、页面缓存、动态页面静态化、servlet缓存、页面内部缓存
4、web服务器缓存:web服务器缓存技术被用来实现CDN加速,被国内主流门户网站大量采用CDN即内容分发网络,就近获取
5、客户端浏览器缓存:缓存页面、缓存数据
缓存技术总结:
缓存本质上就是内存,基于系统访问内存速度远远大于磁盘I/O操作,所以缓存Cache可以加快数据访问速度
2、接下来就是Redis登场了:
NoSql数据库(查询强)VS关系数据库(存储强)
关系数据库的不足
1、不能有效处理多维数据,比如存储Web页面、电子邮箱、音频、视频,等二进制数据
2、高并发读写性能低—当存储数据达到一定规模时候,非常容易发生死锁等并发问题,导致读写性能下降非常严重(可以勉强应付上万次SQL查询,但硬盘I/O无法承受上万次SQL写数据请求)
支持的容量有限-对于关系数据库在一张1350亿条记录的表里进行SQL查询,效率是极其低下而无法忍受
3、数据库的可扩展性和可用性低—传统的关系数据库却没有办法简单通过添加硬件和服务节点来扩展性能和负载能力(不间断升级)
NoSQL数据库的优势
1、易扩展
NOSQL数据库之间无关系,数据库的结构简单
2、大数据量
3、高性能
他们之间的关系
各有之间的特点和使用场景,结合会个web 2.0的数据库发展带来新的思路关,系数据(关注关系)+NoSql数据库(关注储存)
NoSql数据库
BigTable
Dynamo
Mongodb
Cassandra
CouchDB
Redis
Redis简介
它是一个Key-Value储存系统,和Memcached类似,它支持储存的Value类型相对更多,包括String、list(链表)、set(集合)和zset(有序集合)
操作数据库
插入数据
set name value
查询
get name 'value'
修改
set name value
删除
del name
常用的命令
mset 一次设置多个key值
mest key value key2 value
incr 对key的值做++操作
incr age
append 给key的字符串追加value
append name value
keys * - 查询所有的key
keys *
type 返回值类型
type mylist
exists- 验证数据(检查键key是否存在)
exists key
select 选择数据库(Redis数据库编号0-15)
select 1
String类型
Redis的String类型不仅仅是存储字符,还可以储存任何数据,比如jpg图片或系列化的对象
list类型
list类型是一种链表结构,主要功能是push(进栈)、pop(出栈)
命令
lpush 在key对应List的头部添加字符串元素
ipush mylist ' hello'
lrange 显示key对应的list的元素
lrange mylist 0 -1
lpop 从key对应的list的头部删除元素
lpop mylist 'word'
set类型
set类型是String类型的无序集合,底层是通过hash表实现的
命令
sadd 为指定key的set添加元素
sadd myset 'hello'
smembers 显示key对应的set的元素
smembers myset
srem 删除指定key的set中的元素
srem myset 'hello'
Redis高级特性
1、安全性
设置客户端连接后进行任何其他指定前需要使用的密码
2、主从复制
通过主从复制可以允许多个从库拥有和主库相同的数据库副本
3、事物控制
由于redis是单线程处理只能保证一个Client发起的事物中的命令进行连续执行,中间不会插入其他的客户端的命令
4、持久化机制
从内存中数据同步到磁盘中来保证持久化,支持两种方式:一种是snapshotting(快照方式),另一种是Append-only file(aof)的方式
对象储存到redis中
1、序列化和反序列化
2、json
SpringBoot的web开发整合redis
redis和MemCache
一、使用redis的好处
1、速度快,因为数据存在内存总,类似于HashMap,查找和操作时间短
2、支持丰富的数据类型,支持string、list、set 、sorted set 、hash
3、支持事物,操作都是原子性,不会出现并发性问题
4、丰富的特性(可用于缓存、消息)
二、redis与MemCache相比有哪些优势?
1、MemCache所有的值是简单的字符串,redis支持丰富的数据类型
2、redis速度比MemCache快很多
redis可以持久化数据,MemCache只支持内存数据
3、我们来用SpirngBoot把Redis整合上去吧!
1、安装Redis: 直接解压即可,官网下载慢的朋友。这是我网盘链接:https://pan.baidu.com/s/1yd2qv9ZYHead2O3_IOmyCA
提取码:clnm
解压后:
运行:redis-server.exe启动如下:
看见这个说明已经启动完成,注意看,端口号为:6379
接下来我们配置SpringBoot的application.properties文件:
#Redis配置
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址 (默认为127.0.0.1)
spring.redis.host=127.0.0.1
# Redis服务器连接端口 (默认为6379)
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接超时时间(毫秒)
spring.redis.timeout=2000
导入依赖:
<!-- redis配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
编写RedisConfg配置类:
/**
* Project Name:StudySpringApp
* File Name:RedisConfig.java
* Package Name:com.java.config
* Date:2019年6月12日下午2:25:01
* Copyright (c) ©1994-2019 Scjydz.com All Rights Reserved.
*/
package com.java.config;
import java.io.Serializable;
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.StringRedisSerializer;
import com.java.util.ObjectRedisSerializer;
/**
* @Title: RedisConfig.java
* @Package com.java.config
* @Description: TODO(Redis配置类)
* @author lys
* @date 2019年6月12日 下午2:25:01
* Copyright (c) ©1994-2019 Scjydz.com All Rights Reserved.
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<Serializable, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Serializable, Object> template = new RedisTemplate<Serializable, Object>();
template.setConnectionFactory(connectionFactory);
template.afterPropertiesSet();
// redis存取对象的关键配置
template.setKeySerializer(new StringRedisSerializer());
// ObjectRedisSerializer类为java对象的序列化和反序列化工具类
template.setValueSerializer(new ObjectRedisSerializer());
return template;
}
}
我这里使用的序列化和反序列化来进行对对象的储存和读取:
/**
* Project Name:StudySpringApp
* File Name:ObjectRedisSerializer.java
* Package Name:com.java.util
* Date:2019年6月12日下午2:26:44
* Copyright (c) ©1994-2019 Scjydz.com All Rights Reserved.
*/
package com.java.util;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
/**
* @Title: ObjectRedisSerializer.java
* @Package com.java.util
* @Description: TODO(用一句话描述该文件做什么)
* @author lys
* @date 2019年6月12日 下午2:26:44 Copyright (c) ©1994-2019 Scjydz.com All Rights
* Reserved.
*/
public class ObjectRedisSerializer implements RedisSerializer<Object> {
/**
* 定义序列化和反序列化转化类
*/
private Converter<Object, byte[]> serializer = new SerializingConverter();
private Converter<byte[], Object> deserializer = new DeserializingConverter();
/**
* 定义转换空字节数组
*/
private static final byte[] EMPTY_ARRAY = new byte[0];
@Override
public byte[] serialize(Object obj) throws SerializationException {
byte[] byteArray = null;
if (null == obj) {
System.err.println("----------------------------->:Redis待序列化的对象为空.");
byteArray = EMPTY_ARRAY;
} else {
try {
byteArray = serializer.convert(obj);
} catch (Exception e) {
System.err.println("----------------------------->Redis序列化对象失败,异常:" + e.getMessage());
byteArray = EMPTY_ARRAY;
}
}
return byteArray;
}
@Override
public Object deserialize(byte[] datas) throws SerializationException {
Object obj = null;
if ((null == datas) || (datas.length == 0)) {
System.out.println("---------------------------------->Redis待反序列化的对象为空.");
} else {
try {
obj = deserializer.convert(datas);
} catch (Exception e) {
System.out.println("------------------------------------->Redis反序列化对象失败,异常:" + e.getMessage());
}
}
return obj;
}
}
编写Controller测试:
/**
* Project Name:StudySpringApp
* File Name:TestRedisContoller.java
* Package Name:com.java.controller
* Date:2019年6月14日上午11:22:57
* Copyright (c) ©1994-2019 Scjydz.com All Rights Reserved.
*/
package com.java.controller;
import java.io.Serializable;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import com.java.entity.UserEntity;
import com.java.mapper.UserEntityMapper;
import com.java.util.ResponseData;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
/**
* @Title: TestRedisContoller.java
* @Package com.java.controller
* @Description: TODO(用一句话描述该文件做什么)
* @author lys
* @date 2019年6月14日 上午11:22:57
* Copyright (c) ©1994-2019 Scjydz.com All Rights Reserved.
*/
@Api(tags = "测试RedisAPI")
@RestController
@Slf4j
public class TestRedisContoller {
@Autowired
private UserEntityMapper userMapper;
@Autowired
private RedisTemplate<Serializable, Object> redisTemplate;
@ApiOperation(value = "Redis测试", notes = "Redis测试")
// @ApiImplicitParam(name = "id", value = "userid", required = true, paramType =
// "query")
@ApiResponses({ @ApiResponse(code = 200, message = "查询成功", response = UserEntity.class),
@ApiResponse(code = 201, message = "无查询数据", response = Void.class) })
@GetMapping("/testRedis")
public ResponseData testRedis() {
//返回数据统一
ResponseData data = new ResponseData();
//在Redis中获取数据
Object redisuser = redisTemplate.opsForValue().get("userinfo1");
if(redisuser==null) {
log.info("进入数据库查询======================");
List<UserEntity> userinfo = userMapper.selectAll();//这里是从数据库查的数据,根据你实际的数据来,测试也可用假数据
data.getData().put("user",userinfo);
log.info("存入Redis中》》》》》》》》》》》》》》》");
redisTemplate.opsForValue().set("userinfo1", userinfo);
return data;
}
else {
log.info("进入Redis查询》》》》》》》》》》》》》》》》》");
data.getData().put("user", redisuser);
return data;
}
}
}
这里使用了返回参数类:
package com.java.util;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Component;
/**
* 工具类,统一返回值类型
* @author lys
*
* 2019年3月21日
*/
//@Component
public class ResponseData {
private int code = 200;
private String message = "ok";
private Map<String, Object> data = new HashMap<String, Object>();
public ResponseData() {
super();
}
public ResponseData(int code, String message) {
super();
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Map<String, Object> getData() {
return data;
}
public void setData(Map<String, Object> data) {
this.data = data;
}
public static ResponseData ok() {
return new ResponseData(200, "ok");
}
public static ResponseData noFound() {
return new ResponseData(400, "no found resource");
}
public static ResponseData unauthorized() {
return new ResponseData(401, "unauthorized");
}
}
然后启动项目进行测试输入你的项目地址我这里使用了swagger2插件,端口号9998,项目name:spring,所以地址为:http://localhost:9998/spring/swagger-ui.html#,当然没有使用swagger2的朋友可以直接访问浏览器敲回车一样可以。
点击execute执行操作:
查看已经有返回结果给我们了:
然后我们在查看控制台情况:可以看见第一次执行由于Redis里面还没有存在对象,所以第一次是去数据库查询的。
然后我们再运行一次再看控制台情况:进入Redis查询没有进行数据库查询了,已经缓存在Redis中了
swagger2 集成和使用很简单所以就没弄了。如果喜欢的朋友。。希望点个赞,纯手打