瑞吉外卖2.0 Redis 项目优化 Spring Cache MySQL主从复制 sharding-JDBC Nginx

Git版本控制
Linux从安装到实战&瑞吉外卖项目部署
Redis基础

Redis入门 redis.io

nosql没有表的概念




注意关闭防火墙
systemctl stop firewalld
启动redis
src/redis-server ./redis.conf


数据类型


常用命令
字符串 string 操作命令


哈希 hash 操作命令


列表list(类似 栈 )操作命令


集合set 操作命令


sdiff key1 [key2] :key1-key2;
有序集合 sorted set (zset) 操作命令


通用命令

TTL return -1 表示永久;
在Java中操作Redis
介绍

Jedis


Spring Data Redis


Redis服务默认会给16个数据库在redis.windows.conf里面修改

默认是在0号数据库操作,更换数据库:select 1

String

hash


List

Set

ZSet


通用操作,针对不同数据类型都可以操作

项目优化-缓存优化

环境搭建


如何查看本地Ip
配置RedisConfig:为了自定义序列化器
@Configuration
public class RedisConfig extends CachingConfigurerSupport {@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();//默认的Key序列化器为:JdkSerializationRedisSerializerredisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setConnectionFactory(connectionFactory);return redisTemplate;}
}
缓存短信验证码
保存方式:Session-->Redis

@Autowiredprivate RedisTemplate redisTemplate;
@PostMapping("/sendMsg")public R<String> sendMsg(@RequestBody User user, HttpSession session){String phone = user.getPhone();//获取手机号if(StringUtils.isNotEmpty(phone)){//手机号非空//工具类 生成随机的4位验证码String code = ValidateCodeUtils.generateValidateCode(4).toString();log.info("code={}",code);//调用阿里云提供的短信服务API("签名","模板",手机号,动态验证码)完成发送短信//SMSUtils.sendMessage("瑞吉外卖","",phone,code);//需要将生成的验证码保存到Session//session.setAttribute(phone,code);//将生成的验证码保存到SessionredisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);return R.success("手机验证码短信发送成功");}return R.error("短信发送失败");}
@PostMapping("/login")public R<User> login(@RequestBody Map map, HttpSession session){log.info(map.toString());//获取手机号String phone = map.get("phone").toString();//获取验证码String code = map.get("code").toString();//从Session中获取保存的验证码//Object codeInSession = session.getAttribute(phone);//从redis中获得缓存的验证码Object codeInSession = redisTemplate.opsForValue().get(phone);//进行验证码的比对(页面提交的验证码和Session中保存的验证码比对)if(codeInSession != null && codeInSession.equals(code)){//如果能够比对成功,说明登录成功LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(User::getPhone,phone);User user = userService.getOne(queryWrapper);if(user == null){//判断当前手机号对应的用户是否为新用户,如果是新用户就自动完成注册user = new User();user.setPhone(phone);user.setStatus(1);userService.save(user);}session.setAttribute("user",user.getId());//如果用户登录成功,删除redis中缓存的验证码redisTemplate.delete(phone);return R.success(user);}return R.error("登录失败");}
链接redis报错 ERROR org.springframework.boot. ; ERR invalid password;java.io.IOException:
缓存菜品数据

@GetMapping("/list")//改造listpublic R<List<DishDto>> list(Dish dish){List<DishDto> dishDtoList =null;//动态构造keyString key="dish_"+dish.getCategoryId()+"_"+dish.getStatus();////1.先从redis中获取缓存数据,按照菜单分类缓存dishDtoList= (List<DishDto>) redisTemplate.opsForValue().get(key);if(dishDtoList != null) {//2.如果存在!=null,直接返回,不用查询数据库return R.success(dishDtoList);}//构造查询条件LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(dish.getCategoryId() != null ,Dish::getCategoryId,dish.getCategoryId());//添加条件,查询状态为1(起售状态)的菜品queryWrapper.eq(Dish::getStatus,1);//添加排序条件 排序顺序,创建时间倒序queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);List<Dish> list = dishService.list(queryWrapper);dishDtoList = list.stream().map((item) -> {DishDto dishDto = new DishDto();BeanUtils.copyProperties(item,dishDto);Long categoryId = item.getCategoryId();//分类id//根据id查询分类对象Category category = categoryService.getById(categoryId);if(category != null){String categoryName = category.getName();dishDto.setCategoryName(categoryName);}//当前菜品的idLong dishId = item.getId();LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);//SQL:select * from dish_flavor where dish_id = ?List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);dishDto.setFlavors(dishFlavorList);return dishDto;}).collect(Collectors.toList());//3.不存在,需要查询数据库,将查询到的数据缓存到redisredisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.HOURS);//60分钟return R.success(dishDtoList);}
@PostMappingpublic R<String> save(@RequestBody DishDto dishDto){log.info(dishDto.toString());dishService.saveWithFlavor(dishDto);//1.更新完 就清理所有缓存数据//Set keys = redisTemplate.keys("dish_*");//获得所有以‘dish_’开头的key//redisTemplate.delete(keys);//2.精确 清理缓存数据(只清理 被更新类别 的缓存数据)String key="dish_" + dishDto.getCategoryId()+"_1";redisTemplate.delete(key);return R.success("新增菜品成功");}@PutMapping//改造update&savepublic R<String> update(@RequestBody DishDto dishDto){log.info(dishDto.toString());dishService.updateWithFlavor(dishDto);//1.更新完 就清理所有缓存数据//Set keys = redisTemplate.keys("dish_*");//获得所有以‘dish_’开头的key//redisTemplate.delete(keys);//2.精确 清理缓存数据(只清理 被更新类别 的缓存数据)String key="dish_" + dishDto.getCategoryId()+"_1";redisTemplate.delete(key);return R.success("修改菜品成功");}
Spring Cache框架
介绍 基于注解的缓存 (Cache译为缓存)

常用注解


#result: 代表方法返回值(condition关键字里没有result用unless代替); #root.method: 方法对象 ;
#root.args[0] / #p0 / #a0(a0我感觉也行) : 方法第一个参数




使用方式

缓存套餐数据



项目优化—读写分离


Mysql主从复制


配置主库Master



先登录 mysql -uroot -p1234(你的密码)

GRANT REPLICATION SLAVE ON *.* to 'xiaoming'@'%' identified by 'Root@1234';(我的密码比他少两位)

从库Slave #192.168.138.132; root@1234

关闭防火墙链接mysql



change master to master_host='192.168.138.100',master_user='xiaoming',master_password='Root@1234',master_log_file='mysql-bin.000001',master_log_pos=439;

后两个要跟这里的对应;

测试主从复制连接
主库怎么操作,从库也会复制操作;就说明链接成功

读写分离案例
背景

sharding-JDBC介绍

入门案例

项目实现读写分离
直接往主库里面导入,从库就会自动复制;


报错:
create connection SQLException, url: jdbc:mysql://192.168.138.100:3306/reggie?characterEncoding=utf-8, errorCode 0, state 08S01
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
create connection SQLException, url: jdbc:mysql://192.168.138.100:3306/reggie?characterEncoding=utf-8, errorCode 0, state 08S01
修改两个URL:
url: jdbc:mysql://192.168.138.101:3306/rw?characterEncoding=utf-8&useSSL=false
Nginx
Nginx概述



1.5安装wget

4.5 创建文件夹 :mkdir -p /usr/local/nginx ; 6:先编译然后 install; 安装tree命令查看目录结构


Nginx命令
查看版本
要先cd /usr/local/nginx/sbin

检查配置文件正确性

启动和停止

关闭防火墙: systemctl stop firewalld ; 如下页面,访问成功

重新加载配置文件


要写路径启动nginx -->不想写路径;
解决方案:把nginx的二进制文件路径配置到系统的环境变量 实现 nginx 即可启动的效果
vim /etc/profile
PATH=$JAVA_HOME/bin:$PATH # 追加成下面的
PATH=/usr/local/nginx/sbin:$JAVA_HOME/bin:$PATH
source /etc/profile
nginx -s reload # 不报错说明添加环境变量成功
Nginx配置文件结构
全局块、Events块、Http块

Nginx具体应用
部署静态资源



部署html成功
反向代理(用的最多)
负载均衡
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/392034.html
如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!相关文章:

瑞吉外卖2.0 Redis 项目优化 Spring Cache MySQL主从复制 sharding-JDBC Nginx
Git版本控制Linux从安装到实战&瑞吉外卖项目部署Redis基础Redis入门 redis.ionosql没有表的概念注意关闭防火墙 systemctl stop firewalld启动redissrc/redis-server ./redis.conf数据类型常用命令字符串 string 操作命令哈希 hash 操作命令列表list(类似 栈 )操作命令集合…...

【C++】从0到1入门C++编程学习笔记 - 提高编程篇:STL常用容器(map/ multimap容器)
文章目录一、map基本概念二、map构造和赋值三、map大小和交换四、map插入和删除五、map查找和统计六、map容器排序一、map基本概念 简介: map中所有元素都是pairpair中第一个元素为key(键值),起到索引作用,第二个元素…...

十一、Gio->Resource
struct GResource {/* No available fields */ }应用程序applications和库libraries通常包含二进制或文本数据,这些数据实际上是应用程序的一部分,而不是用户数据。例如GtkBuilder .ui文件,splashscreen图像,GMenu标记XML, CSS文件…...

vm+centos设置NAT
centos 设置 NAT模式 系统环境 VMWare: Workstation16 Pro centos:7.9 [rootowl owl]# cat /etc/centos-release CentOS Linux release 7.9.2009 (Core)[rootowl owl]# uname -a Linux owl.com 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 U…...

Metaprogram 对一个程序进行编程
metaprogram含有对一个程序进行编程的意思,换句话说,编程系统将会执行我们所写的代码,来生成新的代码,而这些新的代码才真正实现了我们所期望的功能,通常而言,metaprogram 这个概念意味着一种反射的特性&am…...

【测开篇】测试基础
文章目录名词解释:1. 什么是需求?2. 什么是Bug?3. 什么是测试用例?软件的生命周期开发模型1. 瀑布模型2. 螺旋模型3. 增量模型和迭代模型4. 敏捷模型测试模型1. V模型2. W模型软件测试的生命周期Bug如何描述一个Bug?Bu…...

力扣第331场周赛题解
rankT1T2T3T4331 / 42560:01:460:06:18 (1)0:11:580:57:29 (4) T1 从数量最多的堆取走礼物模拟题,每次操作找出最大值maxxmaxxmaxx并将其变成sqrt(maxx)sqrt(maxx)sqrt(maxx),kkk次操作后求和。 数据范围很小,可以暴力模拟,更好的…...

基于LDA模型的非监督分类算法介绍
前言基于LDA(Latent Dirichlet Allocation)模型的非监督分类算法,将LDA模型从文本分析的应用过渡到遥感高分辨率影像处理的应用,利用Gibbs采样方法设计基于LDA模型的非监督分类算法,并使用IDL语言实现。在一定程度上解…...

以安全有效为目标的综合运营
一、安全行业的现状所有做安全的方案大多会在开始介绍安全的案例,都会列举近期国内外发生的重大安全事件, 基本上都是惨不忍睹,危害巨大。这里就不一一列举了,稍微了解这个行业的人都能看到大量的案例。但业界又有个很奇怪的现象就…...

mysql常见面试题--03 事务常考题以及事务的隔离
什么是事务? 对数据库的一系列操作,要么全执行,要么不执行. 事务时逻辑上的一组操作,要么全部执行,要么都不执行。 事务的三大特征 原子性 A 事务是最小执行单位,要么全部执行,要么都不执行一致性 C 事务执行前后&…...

数据库管理工具dbForge SQL Complete 如何增强总两个开发团队之间的协作
Devart 提供包括Oracle、SQL Server、MySQL、PostgreSQL、InterBase以及Firebird在内的专业数据库远程管理软件,dbForge Studio for MySQL是一个在Windows平台被广泛使用的MySQL客户端,它能够使MySQL开发人员和管理人员在一个方便的环境中与他人一起完成…...

Cuda Streams的概述(一)-- Cuda介绍
最近在做有关Cuda的一个项目, 碰到匪夷所思的问题,在异步的时候发现并没有达到预期的效果,程序没有异步起来,然后在网上找了一个Nvida的有关Cuda Streams的一个ppt,然后照着里面的提示,使程序达到了异步的效…...

Docker介绍与入门
1. Mac版Docker(DfM) Mac版Docker底层是基于Linux VM运行的。Server的OS/Arch属性中显示的值是linux/amd64Client组件是原生的Mac应用,运行在Mac操作系统Darwin内核之上 2. 升级Docker引擎 需要重视升级前的每个前置条件,包括确保容器配置了正确的重启…...

Docker引擎介绍
1. Docker引擎简介 Docker引擎是用来运行和管理容器的核心软件Docker引擎主要的组件构成:Docker客户端(Docker Client), Docker守护进程(Docker deamon),containerd以及runc。 2. Docker引擎详…...

纵观Docker
1. 运维视角 两个主要部件: Docker客户端和Docker daemon(daemon实现了Docker引擎的API)使用linux默认安装的时候,客户端与daemon之间的通信是通过本地IPC/UNIX Socket完成的 1.1. 容器 docker container run – 从镜像启动容…...

Cuda Streams的概述(二) -- cuda Streams介绍
Cuda Streams Streams介绍: 流可以看成是在设备上work的一个队列,host端将work加入队列,然后继续添加。设备在资源free时,开始调度streams里面的work。CUDA的操作也是在流里面,比如Kernel的启动,内存的拷…...

Cuda Streams的概述(三)-- 并发内存拷贝
并发内存拷贝 首先,回顾一下CUDA的内存。 设备内存: 通过cudaMalloc申请内存。不能分页 主机端可分页内存: 默认申请方式(malloc, calloc,new)可以在OS中调入和调出。 主机端页锁内存…...

Cuda Streams的概述(四)-- 同步
同步 同步的APIs 同步所有的事情 //阻塞host端,直到所有的CUDA调用完成。 cudaDeviceSynchronize();同步主机端特定的流 //阻塞host端,直到流里的CUDA调用完成。 cudaStreamSynchronize(stream); 通过主机端或设备用events CUDA Events 当操作在流…...

Cuda Streams的概述(五)-- Streaming性能
Streaming性能 profiling工具 windows: Nsight Visual Studio EditionNVIDIA Visual Profiler Linux,Mac: Nsight Eclipse EditionNVIDIA Visual Profilernvprof NVVP PROFILER TIMELINE Host API CallsMulti-threadedMulti-GPUMulti-pro…...

Cuda Streams的概述(六)-- 常见问题
常见问题 问题1:使用默认流 问题2:内存传输问题 问题3:隐式同步 问题4:主机端的限制 问题5:启动overhead限制 问题6:过度同步 问题7:PROFILER OVERHEAD case 1-A for(int i0;i<repeat;i) {kernel<<<1,1,0,stream1>>>();ke…...