1. Redis的引入:
问题:
目前我们可以使用技术完成WEB功能的开发,访问流程浏览器-->服务器--->数据库。浏览器发起请求,被服务器接收后进行处理,
服务器中的代码执行,从数据库中查询到指定的数据,返回给服务器,服务器处理后将数据响应给浏览器,最终用户在浏览器中查
看到想要的数据。不同用户发起的请求,在后端处理的时候需要使用到相同的数据,比如:查询所有的用户信息。但是目前不用的用
户的请求,再被后端接受到后,都会开启一个线程,并且都会从数据库中查询数据。不同的用户哪怕使用相同的数据,也要各自从数
据库中单独查询,造成数据库的压力过大,并且数据从数据库中获取的效率是比较低的,怎么办?
解决:
使用缓存技术。那么不同的用户都要使用的数据,可以考虑缓存到ServletContext对象中。
但是ServletContext对象有如下缺点:
① 没有提供合理的底层数据库结构,现有结构过于简单。
② ServletContext缓存的数据无法设置缓存的有效时间。
③ ServletContext对象无法夸应用实现缓存共享。
那么,需要发明一个新的缓存技术,能够夸应用或者夸服务器主机实现缓存的共享,那么也就是说该缓存技术可以
在一台主机上独立运行实现缓存即可。
实现:
redis。
2. Redis的介绍
常见的No-SQL数据库(缓存库):
memcached :键值对,内存型数据库,所有数据都在内存中。
Redis:和Memcached类似,还具备持久化能力。
HBase:以列作为存储。
MongoDB:以Document做存储。
Redis的介绍:
存储结构: key-value.
开发语言: C语言。
数据存储: 存储安装了redis的主机内存中。
存储单元: 在redis中将内存库分为16384个槽(slot).
存储算法: key进行crc16得到key的数值,然后后16384取余,余数就是存储的slot。
存储大小: 每个slot中可以存储多个键值对数据,没有上限要求,但是单个的键值对数据最大512M。
3. 边路缓存思想:
① 处理请求,需要使用数据,先从redis缓存库中查询
② 判断redis缓存库查询的结果是否存在,如果存在则继续处理请求即可。
如果不存在,则从持久化数据库中查询。
③ 查询持久化数据库,继续处理请求,并将查询的数据重新存储到redis中。
4. 基于Docker安装Redis
① 保证Docker启动
② 使用Docker命令下载镜像: docker pull 镜像名称:版本号
③ 根据镜像创建并启动容器: docker run 参数 镜像名:版本号
5. Redis的常用命令:
value数据类型:
String:存储的是键值对,值是String类型,比如 key:"name" value:"张三"
list: 存储的是键值对,值是list类型, 比如: key:"aa" value:["aa","bb","cc"]
set: 存储的是键值对,值是set类型,比如: key:"aa",value:线程结构的数据结构,不允许重复值
Hash: 存储的是键值对,值是Hash类型,比如: key:"aa",value: hash结构类似java的HashMap结构。
key"bb" value
field data
field data
field data
....
sorted set: 存储的是键值对,值是sortedSet类型,比如: key:"aa" ,value:"有序的集合"。
Stream类型(Redis5以后新版本类型): 存储的是键值对,值是Stream类型。
注意:
在redis中不同的数据类型提供了不同的操作命令,使用命令来区分采用什么数据类型存储数据!
redis的常用命令:
String类型的命令:
set key value: 存储键值对数据,同名key覆盖
get key :根据key获取value
setnx key value: 如果key存在则返回0,不存在则存储,返回1,同名key不存储
setex ket seconds value: 存储的同时设置有效期,同名key覆盖。
Hash类型的命令
hset key field value: 存储键值对数据,值也是一组键值对,每次存储一组!可以多次使用
hget key field: 获取key存储的hash结构中某个field的值
hmset key field value filed value..: 一次存储多组键值对数据
hmget key field field.. :一次获取多组键值对的值
hvals key: 获取所有的value
hgetall key: 获取所有的field和value
hdel key field: 删除指定的field
List类型的命令
rpush key value value : 尾插数据到列表
lrange key start stop: 获取从start到stop之间的数据包括start和stop,stop的值为-1表示获取到末尾。
llen key:获取列表长度
lpush key value value:头插数据到列表
lrem key count value:删除指定数量的value,count为正数表示从左往右,负数表示从右往左。
Set类型的命令:
sadd key value value value: 存储数据到set集合中,value重复不存储
scard key: 查看大小
smembers key: 查看所有内容
SortedSet类型的命令:
zadd key score value score value: 存储数据,socre为排序值没有任何实际意义
zrange key start stop [withscores]: 查看指定区间内的数据
Stream类型的命令:
xadd key id field value field value: 指定存储数据的Id
xadd key * filed value field value :使用自动生成的Id
xrange key start stop: 获取id在start和stop区间内容的数据
xrange key - +: 获取所有id的数据
Key的操作命令:
exists key:判断key是否存在,0表示不存在,1表示存在。
expire key seconds:给指定的key添加有效期
ttl key: 查看key的剩余到期时间,已经到期返回-2, 永久key返回-1.
del key: 删除
keys *:查看所有key
flushdb: 删除所有key
6. redis的持久化策略:
持久化:
当redis启动的时候会将硬盘中的数据读取到内存中。
注意在整个数据操作过程,数据都是在内存中的。
持久化的策略:
RDB方式:
默认方式,在指定间隔的时间后对redis中的数据生成快照存储到硬盘中的dump.rdb文件中!
优点:直接持久化的是数据本身,恢复效率高!
缺点:保存点之间的数据会丢失。
AOF方式:
将对redis所有的修改命令全部记录到日志文件中,需要恢复的时候只需要将日志文件中的命令执行一遍即可。
优点: 不会丢失数据。
缺点: 恢复效率低。
开启办法: 修改redis.conf的配置文件即可。
7. java项目和Redis数据库之间的数据交互:
问题:
redis官方提供了和java项目实现数据交互的技术,叫Jedis,但是使用原生的Jedis操作redis比较麻烦,就好比
使用jdbc操作mysql一样,那么怎么办?
解决:
对原生的Jedis进行封装即可。
实现:
spring-cache技术: 基于注解实现的。
spring-data-redis技术:
是Spring-data的子项目,SpringData是顶层项目。
只需要SpringBoot项目中导入Spring-data-redis技术的启动器依赖,这样SpringBoot项目中
就有了redis操作的封装的代码并且会自动化的构建出spring-data-redis提供的bean对象。我们
直接在代码中使用依赖注入从Spring容器中获取redisTemplate对象使用即可。
使用:
① 创建SpringBoot项目
② 配置依赖
继承parent的依赖
配置web启动器依赖
配置mybatis的依赖
配置spring-data-redis的依赖
配置单元测试的启动器依赖
③ 在springboot的配置文件中配置
配置端口号
配置数据库的参数
配置redis的链接地址
④ 在代码中依赖注入redisTemplate对象完成对redis的操作。
redisTemplate.opsForXXX().功能操作方法!
内容:
redisTemplate.opsForValue() --> String类型数据 java中的数据必须转换为String类型
redisTemplate.opsForList() --> List类型数据
redisTemplate.opsForHash() --> Hash类型数据
redisTemplate.opsForSet() --> Set类型数据
redisTemplate.opsForZSet() --> SortedSet类型数据
redisTemplate.opsForStream() --> Stream类型数据
redisTemplate.key**的操作方法
8. 自定义key和value的序列化器:
问题:
目前我们可以在项目中使用redisTemplate对象,将java中的数据缓存到redis中,或者将redis中的缓存数据
获取到java项目中使用。优先推荐使用opsForValue方式来操作,也就是将Java中的数据以字符串的形式存储到
redis中。而在java的数据有String类型和其他引用类型,如果java中的数据本身就是String类型,那么可以直接
操作,如果java中的是其他的引用类型,比如User对象类型,List集合类型,HashMap集合类型等,怎么操作呢?
解决:
存储:
将Java中的数据转换为String数据,然后再存储到Redis中。
获取:
从redis中获取存储的String类型数据,然后再转换为对用的java类型。
转换格式:
java对象-->二进制字符串-->存储到redis java对象必须序列化
Java对象-->json字符串--->存储到redis java对象必须序列化
实现:
① 我们自己写代码将java对象转换为字符串数据,调用第三方的工具类实现,比如:Gson.
② redisTemplate底层帮我实现java对象和字符串数据的互转,必须配置自定义的序列化器。
序列化器的作用就是实现java对象和字符串数据的互转。
序列化器:
JdkSerializationRedisSerializer:
①默认的序列化器
②key和value都会使用该序列化器转换为二进制的字符串后存储到redis中。
③直接使用java类型作为key获取,底层会先将Java类型转换的key转换为二进制的字符串后再获取值,
然后将值再调用序列器转换为对应的Java对象返回。
④ 使用的时候只需要将redisTemplate的key和value的泛型设置为object类型,无需任何其他的配置即生效!
缺点:
数据存储到redis中的阅读性太差!
优点:
简单好用。
注意:
java对象必须实现序列化。
OxmSerializer:
实现Java对象和XML类型的字符串的互转!使用的时候需要配置额外的依赖!几乎不用!
StringRedisSerializer:
只能对Java的String类型数据进行转换。一般用做key的序列化器。
java的String类型数据是什么存储到redis中的就是什么!
GenericToStringSerializer:
使用麻烦!
Jackson2JsonRedisSerializer
实现java对象和Json字符串的互转。
优点:速度快,效率高
缺点: 能将java对象转换为json字符串,但是反过来会将redis中存储的json字符串统一转换为Java的LinkedHashMap类型。
GenericJackson2JsonRedisSerializer:
实现 :java对象和json字符串的互转
优点:速度快,效率高,哪个java对象转换的json字符串,反过来的时候也会将json转换为对应的java对象!
序列器的使用:
目前我们使用的redisTemplate对象是通过启动器依赖中的配置类完成的自动化配置,redisTemplate对象在创建的时候
它的keySerializer和valueSerializer属性都被默认赋值为JdkSerializationRedisSerializer了,而我们现在想
自定义配置序列化器,那么redisTemplate的bean对象得我们自己创建和配置。我们只要自己创建配置类,并在配置类中
配置redisTemplate的bean对象,并给keySerializer和valueSerializer属性自定义赋值即可。
内容:
//自定义配置RedisTemplate对象
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String,Object> redisTemplate=new RedisTemplate<>();
//自定义key的序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
//自定义value的序列化器
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//设置工厂
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
版权声明:本文为weixin_67707901原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。