六、Redisweb实践 网页缓存
1.创建springboot项目
2.选择组件
Lombok
spring mvc
spring data redis
spring data jpa
3.编写配置文件
### 数据库访问配置 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://192.168.66.100:3307/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 ######################################################## ### Java Persistence Api --y ######################################################## # Specify the DBMS spring.jpa.database = MYSQL # Show or not log for each sql query spring.jpa.show-sql = true # Hibernate ddl auto (create, create-drop, update) spring.jpa.hibernate.ddl-auto = update # Naming strategy #[org.hibernate.cfg.ImprovedNamingStrategy #org.hibernate.cfg.DefaultNamingStrategy] spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy # stripped before adding them to the entity manager) spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect ######################################################## ### 配置连接池数据库访问配置 ######################################################## #Redis服务器连接地址 spring.redis.host=192.168.66.100 #Redis服务器连接端口 spring.redis.port=6379 #连接池最大连接数(使用负值表示没有限制) spring.redis.pool.max-active=8 #连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.pool.max-wait=-1 #连接池中的最大空闲连接 spring.redis.pool.max-idle=8 #连接池中的最小空闲连接 spring.redis.pool.min-idle=0 #连接超时时间(毫秒) spring.redis.timeout=30000 logging.pattern.console=%d{MM/dd HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n
4.创建实体类
package com.zj.redis.pojo; import lombok.Data; import javax.persistence.*; @Data @Entity @Table(name = "goods") public class GoodsEntity { //自增ID @Id @GeneratedValue(strategy= GenerationType.IDENTITY)//自增 private Long id; // 商品名字 private String goodsName; // 订单id private String orderId; // 商品数量 private Integer goodsNum; // 商品价格 private Double price; }
5.编写持久层
package com.zj.redis.mapper; import com.zj.redis.pojo.GoodsEntity; import org.springframework.data.jpa.repository.JpaRepository; /* GoodsEntity:表示的是实体类 Long:表示的是实体的主键的类型 */ public interface GoodsMapper extends JpaRepository<GoodsEntity,Long> { }
6.编写业务层
package com.zj.redis.service; import com.zj.redis.mapper.GoodsMapper; import com.zj.redis.pojo.GoodsEntity; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Optional; @Service public class GoodsService { @Resource private GoodsMapper goodsMapper; //根据商品的id查询商品的信息 public GoodsEntity selectById(Long id) { Optional<GoodsEntity> goodsEntity = goodsMapper.findById(id); if ( goodsEntity.isPresent()){ return goodsEntity.get(); } return null; } }
7.编写控制层
package com.zj.redis.controller; import com.zj.redis.pojo.GoodsEntity; import com.zj.redis.service.GoodsService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController public class GoodsController { @Resource private GoodsService goodsService; //根据id查询商品 @GetMapping("/goods") public GoodsEntity findById(String id) { return goodsService.selectById(Long.valueOf(id)); } }
8.启动mysql的docker容器
#查看全部docker容器 [root@localhost /]# docker ps -a #启动MySQL容器 [root@localhost /]# docker start 43f
9.navicat连接mysql容器
10.运行项目
数据库出现该表表示项目搭建成功!
11.浏览器请求
12.下载压测工具Jmeter并启动
13.修改语言
14.创建压测
添加线程组
15.添加HTTP请求
16.添加压测结果报告
没有加缓存的吞吐量:
17.添加redis缓存
package com.zj.redis.service; import com.alibaba.fastjson.JSON; import com.zj.redis.mapper.GoodsMapper; import com.zj.redis.pojo.GoodsEntity; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.annotation.Resource; @Service public class GoodsService { @Resource private GoodsMapper goodsMapper; @Resource private StringRedisTemplate stringRedisTemplate; //根据商品的id查询商品的信息 public GoodsEntity selectById(Long id) { String goodString = stringRedisTemplate.opsForValue().get("good:" + id); //判断有没有缓存 if (StringUtils.isEmpty(goodString)) { //从数据库查询信息 GoodsEntity goodsEntity = goodsMapper.findById(Long.valueOf(id)).get(); //将对象转为json格式 String goodsEntityJson = JSON.toJSONString(goodsEntity); //添加到redis缓存 stringRedisTemplate.opsForValue().set("good:" + id, goodsEntityJson); return goodsEntity; }else { //字符串转为对象类型 GoodsEntity goodsEntity = JSON.parseObject(goodString, GoodsEntity.class); return goodsEntity; } } }
开启redis:
[root@localhost src]# ./redis-server ../redis.conf
启动项目,访问
发现缓存中出现good。
18.继续压力测试
添加缓存后的吞吐量达到8400多。
总结:10000并发在不添加缓存的吞吐量是1062,在添加缓存后的吞吐量是8496.
七、Redis配置文件详解
在Redis的解压目录下有个很重要的配置文件 redis.conf ,关于Redis的很多功能的配置都在此文件中完成的,一般为了不破坏安装的文件,出厂默认配置最好不要去改。
units单位
配置大小单位,开头定义基本度量单位,只支持bytes,大小写不敏感。
INCLUDES
Redis只有一个配置文件,如果多个人进行开发维护,那么就需要多个这样的配置文件,这时候多个配置文件就可以在此通过 include /path/to/local.conf 配置进来,而原本的 redis.conf 配置文件就作为一个总闸。
NETWORK
参数:
- bind:绑定redis服务器网卡IP,默认为127.0.0.1,即本地回环地址。这样的话,访问redis服务只能通过本机的客户端连接,而无法通过远程连接。如果bind选项为空的话,那会接受所有来自于可用网络接口的连接。
- port:指定redis运行的端口,默认是6379。由于Redis是单线程模型,因此单机开多个Redis进程的时候会修改端口。
- timeout:设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接。默认值为0,表示不关闭。
- tcp-keepalive :单位是秒,表示将周期性的使用SO_KEEPALIVE检测客户端是否还处于健康状态,避免服务器一直阻塞,官方给出的建议值是300s,如果设置为0,则不会周期性的检测。
GENERAL
具体配置详解:
- daemonize:设置为yes表示指定Redis以守护进程的方式启动(后台启动)。默认值为 no
- pidfile:配置PID文件路径,当redis作为守护进程运行的时候,它会把 pid 默认写到 /var/redis/run/redis_6379.pid 文件里面
- loglevel :定义日志级别。默认值为notice,有如下4种取值:
debug(记录大量日志信息,适用于开发、测试阶段)
verbose(较多日志信息)
notice(适量日志信息,使用于生产环境)
warning(仅有部分重要、关键信息才会被记录)
- logfile :配置log文件地址,默认打印在命令行终端的窗口上
- databases:设置数据库的数目。默认的数据库是DB 0 ,可以在每个连接上使用select 命令选择一个不同的数据库,dbid是一个介于0到databases - 1 之间的数值。默认值是 16,也就是说默认Redis有16个数据库。
SNAPSHOTTING
这里的配置主要用来做持久化操作。
参数:
save:这里是用来配置触发 Redis的持久化条件,也就是什么时候将内存中的数据保存到硬盘
save 900 1:表示900 秒内如果至少有 1 个 key 的值变化,则保存 save 300 10:表示300 秒内如果至少有 10 个 key 的值变化,则保存 save 60 10000:表示60 秒内如果至少有 10000 个 key 的值变化,则保存
REPLICATION
参数:
- slave-serve-stale-data:默认值为yes。当一个 slave 与 master 失去联系,或者复制正在进行的时候,
slave 可能会有两种表现:
- 如果为 yes ,slave 仍然会应答客户端请求,但返回的数据可能是过时,或者数据可能是空的在第一次同步的时候
- 如果为 no ,在你执行除了 info he salveof 之外的其他命令时,slave 都将返回一个 "SYNC with master in progress" 的错误
- slave-read-only:配置Redis的Slave实例是否接受写操作,即Slave是否为只读Redis。默认值为yes。
- repl-diskless-sync:主从数据复制是否使用无硬盘复制功能。默认值为no。
- repl-diskless-sync-delay:当启用无硬盘备份,服务器等待一段时间后才会通过套接字向从站传送RDB文件,这个等待时间是可配置的。
- repl-disable-tcp-nodelay:同步之后是否禁用从站上的TCP_NODELAY 如果你选择yes,redis会使用较少量的TCP包和带宽向从站发送数据。
SECURITY
requirepass:设置redis连接密码。
比如: requirepass 123 表示redis的连接密码为123。
CLIENTS
参数:
maxclients :设置客户端最大并发连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件。 描述符数-32(redis server自身会使用一些),如果设置 maxclients为0 。表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
MEMORY MANAGEMENT
参数:
- maxmemory:设置Redis的最大内存,如果设置为0 。表示不作限制。通常是配合下面介绍的maxmemory-policy参数一起使用。
- maxmemory-policy :当内存使用达到maxmemory设置的最大值时,redis使用的内存清除策略。有以下几种可以选择:
1)volatile-lru 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )
2)allkeys-lru 利用LRU算法移除任何key
3)volatile-random 移除设置过过期时间的随机key
4)allkeys-random 移除随机ke
5)volatile-ttl 移除即将过期的key(minor TTL)
6)noeviction noeviction 不移除任何key,只是返回一个写错误 ,默认选项
- maxmemory-samples :LRU 和 minimal TTL 算法都不是精准的算法,但是相对精确的算法(为了节省内存)。随意你可以选择样本大小进行检,redis默认选择3个样本进行检测,你可以通过maxmemory-samples进行设置样本数。
APPEND ONLY MODE
参数:
- appendonly:默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,Append Only File是另一种持久化方式, 可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入appendonly.aof文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认值为no。
- appendfilename :aof文件名,默认是"appendonly.aof"
- appendfsync:aof持久化策略的配置;no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快;always表示每次写入都执行fsync,以保证数据同步到磁盘;everysec表示每秒执行一次fsync,可能会导致丢失这1s数据
LUA SCRIPTING
参数:
lua-time-limit:一个lua脚本执行的最大时间,单位为ms。默认值为5000.
REDIS CLUSTER
参数:
- cluster-enabled:集群开关,默认是不开启集群模式。
- cluster-config-file:集群配置文件的名称。
- cluster-node-timeout :可以配置值为15000。节点互连超时的阀值,集群节点超时毫秒数
- cluster-slave-validity-factor :可以配置值为10。