Java项目拷打(外卖+点评)

打印 上一主题 下一主题

主题 2047|帖子 2047|积分 6141

一、点评星球(黑马点评)

1、项目概述

1.1、项目简介

本项目是基于Spring Boot与Redis深度整合的前后端分离的点评平台。系统以Redis为核心技能支持,重点办理高并发场景下的缓存穿透、击穿、雪崩等题目,涵盖商户展示、优惠券秒杀、达人探店、社交互动等创新功能。
1.2、项目亮点



  • 使用 Redis 办理了在集群模式下的 Session共享题目,使用双拦截器实现用户的登录校验和权限革新
  • 运用Cache Aside模式办理数据库与缓存的一致性题目,通过自动更新结合超时删除包管最终一致性
  • 使用 Redis 对高频访问的信息进行缓存,降低数据库查询压力,办理了缓存穿透、雪崩、击穿题目
  • 使用 Redis + Lua脚本实现对用户秒杀资格的预检,同时用乐观锁办理秒杀产生的超卖题目
  • 使用 Redisson分布式锁办理在集群模式下一人一单的线程安全题目
  • 基于RabbitMQ作为消息队列,实现异步秒杀下单
  • 使用Redis的 ZSet 数据布局实现了点赞排行榜功能,使用Set 聚集实现关注、共同关注功能
1.3、核心功能

用户服务


  • 短信登录(Redis替换Session实现集群共享,双拦截器保障Token革新)
商户服务


  • 多级缓存优化(Cache Aside模式 + Redisson读写锁保障双写一致性)
  • 缓存异常处置惩罚:空值缓存防穿透、互斥锁/逻辑过期防击穿、随机TTL防雪崩
秒杀服务


  • 分布式锁(Redisson实现)办理集群环境下“一人一单”线程安全题目
  • 异步下单优化:Redis Lua脚本预检库存 + RabbitMQ消息队列异步处置惩罚订单
社交服务


  • 达人探店条记(发布、点赞排行榜基于ZSet实现)及挚友关注(Set聚集实现共同关注)
2、使用 Redis 办理了在集群模式下的 Session 共享题目,使用拦截器实现了用户的登录校验和权限革新

3、运用Cache Aside模式办理数据库与缓存的一致性题目,通过自动更新结合超时删除包管最终一致性

4、使用 Redis 对高频访问的信息进行缓存,降低数据库查询压力,办理了缓存穿透、雪崩、击穿题目

5、使用 Redis + Lua脚本实现对用户秒杀资格的预检,同时用乐观锁办理秒杀产生的超卖题目

6、使用 Redisson分布式锁办理在集群模式下一人一单的线程安全题目

7、基于RabbitMQ作为消息队列,实现异步秒杀下单

8、使用Redis的 ZSet 数据布局实现了点赞排行榜功能,使用Set 聚集实现关注、共同关注功能

链接:
链接1
链接2
链接3
二、校园生存服务平台(苍穹外卖)

1、项目概述

1.1、项目简介

本项目是基于Spring Boot的校园生存服务系统,分为管理端(供校内商家使用)和用户端(微信小步伐)。管理端包括员工信息、商品及分类的管理,订单状态跟踪等功能;用户端在线欣赏商品,添加购物车及下单等功能。
1.2、项目亮点



  • 登录及身份验证使用JWT令牌技能,用自定义拦截器完成用户认证,通过ThreadLocal优化鉴权逻辑
  • 使用Redis缓存高频数据如同分类商品,并使用SpringCache优化代码,提高系统性能和响应速度
  • 使用Nginx用作HTTP服务器,部署静态资源,反向代理和负载平衡
  • 通过webSocket实现客户端与服务端的长连接,并实现来单提示及客户催单等功能
  • 使用SpringTask实现订单状态的定时处置惩罚,超时自动取消订单等功能
1.3、核心功能

管理端
1、用户登录(JWT、ThreadLocal)
2、员工信息维护
3、商品管理
4、分类管理
5、订单状态跟踪
6、来单/催单提示(webSocket实时推送)
7、Spring Cache缓存菜品信息
8、定时任务处置惩罚超时订单(Spring Task)
用户端(微信小步伐)
1、微信登岸
2、商品欣赏(Redis缓存)
3、购物车管理
4、下单付出
1.4 模块作用

序号模块作用1sky-take-outmaven父工程,同一管理依靠版本,聚合其他子模块2sky-common子模块,存放公共类,例如:工具类、常量类、异常类等3sky-pojo子模块,存放实体类、VO、DTO等4sky-server子模块,后端服务,存放设置文件、Controller、Service、Mapper等 2、JWT令牌+ThreadLocal

2.1、JWT登录流程

使用JWT令牌和自定义拦截器完成用户认证的流程如下:


  • 用户登录时,客户端发送用户名和密码给服务器请求令牌,服务器验证通过后天生包罗用户信息的JWT令牌并返回给客户端。
  • 客户端收到JWT令牌后将其存储在本地(如localStorage或cookie),后续每次请求都在请求头中携带该令牌(如Authorization:Bearer )。
  • 服务器端的自定义拦截器会拦截全部请求,首先从请求头中提取JWT令牌并进行解析验证(包括检查令牌是否存在、签名是否有效、是否过期等),若令牌不存在或验证失败则直接返回401未认证错误。
  • 当JWT令牌验证通过后,拦截器将解析出的用户信息存储在ThreadLocal中,使本次请求的后续业务处置惩罚流程可以直接获取用户信息,克制重复解析JWT令牌。
  • 请求处置惩罚完成后,拦截器会调用remove()方法扫除ThreadLocal中的用户信息,确保不会发生内存泄漏。
2.2、ThreadLocal使用过多会造成的影响?怎么办理内存泄漏的题目?

每个线程都有⼀个ThreadLocalMap的内部属性,map的key是ThreaLocal,定义为弱引用,value是强引用类型。垃圾接纳的时间会⾃动接纳key,但对应的 Value 仍然是强引用,且线程未结束时,ThreadLocalMap 会一直持有该 Value,导致内存泄漏。
办理⽅法:每次使⽤完ThreadLocal就调⽤它的remove()⽅法,手动将对应的键值对删除,从⽽克制内存泄漏
2.3 JWT的构成:

它由三部分构成:header(头部)、payload(载荷)、signature(签名)


  • Header(头部) 作用:形貌令牌的元数据,如签名算法(如HS256、RS256)和令牌类型(固定为JWT)。
  • Payload(负载) 作用:携带实际的数据(声明),分为三类:
    预定义声明:标准字段,如 iss(签发者)、exp(过期时间)、sub(主题)等。
    公开声明:自定义公共字段,需克制冲突(发起通过IANA 注册)。
    私有声明:双方约定的自定义数据。
  • Signature(签名)作用:验证令牌的完备性和真实性。天生方式:将编码后的 Header 和 Payload 拼接后通过 Header 中指定的算法(如 HS256)和密钥进行签名。
3、Redis

3.1项目中哪里用到redis了,缓存的粒度是什么?key,value怎样定义?

缓存商品 用户端小步伐展示的商品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大。结果是系统响应慢、用户体验差。通过Redis来缓存商品数据,减少数据库查询操作。缓存逻辑是每个分类的商品下缓存一份数据,数据库中商品数据有变动时实时清算数据。key是分类的id,value是该分类下全部商品信息
3.2、数据库与redis怎样实现的数据同步

在项目中,我们采用分布式锁策略实现数据库与Redis的数据同步。通过Redis分布式锁(如Redisson)对数据ID细粒度加锁,确保同一时间只有一个请求能修改数据;在锁内严格按"先更新数据库→再删除缓存"的次序操作,包管后续请求必然读取最新数据;
因为有库存代价等信息所以不适合用延时双删)。
修改频率较低所以加锁性能消耗不高
4、Nginx

4.1 负载平衡:

Nginx 的负载平衡功能答应将请求分发给多个应用服务器,以平衡负载和提高系统的可扩展性和可靠性。下面是一些常用的 Nginx 负载平衡设置方法:


  • 轮询:这是默认的负载平衡策略。Nginx 将请求依次分发给每个后端服务器,确保每个服务器都能获得相同的请求数量。
  • IP 哈希(IP Hash):Nginx 使用客户端 IP地址的哈希值来决定将请求发送给哪个后端服务器。
  • 加权轮询:可以为每个后端服务器设置权重,高权重的服务器将获得更多的请求。这种方式可以根据服务器的性能和处置惩罚能力来分配负载。
    我们项目用的是轮询方式,共有2台后端服务器(一台本机,一台虚拟机)
    在nginx.conf设置:
  1. upstream webservers{
  2.           server 127.0.0.1:8080 weight=90 ;
  3.           #server 127.0.0.1:8088 weight=10 ;
  4.         }
复制代码
4.2 反向代理与正向代理:

反向代理隐藏服务器,正向代理隐藏客户端。


  • 正向代理是客户端发送请求后通过代理服务器访问目的服务器,代理服务器代表客户端发送请求并将响应返回给客户端。正向代理隐藏了客户端的真实身份和位置信息,为客户端提供代理访问互联网的功能。
  • 反向代理是位于目的服务器和客户端之间的代理服务器,它代表服务器吸收客户端的请求并将请求转发到真正的目的服务器上,并将得到的响应返回给客户端。反向代理隐藏了服务器的真实身份和位置信息,客户端只知道与反向代理进行通信,而不知道真正的服务器。
反向代理优点:


  • 提高访问速度,因为nginx本身可以进行缓存,如果访问的同一接口,并且做了数据缓存,nginx就直接可把数据返回,不必要真正地访问服务端,从而提高访问速度。
  • 进行负载平衡,把大量的请求按照我们指定的方式平衡的分配给集群中的每台服务器。
  • 包管后端服务安全因为一般背景服务地址不会袒露,所以使用欣赏器不能直接访问,可以把nginx作为请求访问的入口,请求到达nginx后转发到具体的服务中,从而包管后端服务的安全。
反向代理设置。在nginx.conf设置
  1. server {
  2.         listen       80;
  3.         server_name  localhost;
  4.         # 反向代理,处理管理端发送的请求
  5.         location /api/ {
  6.                         proxy_pass   http://localhost:8080/admin/;
  7.             #proxy_pass   http://webservers/admin/;
  8.         }
  9.                
  10.                 # 反向代理,处理用户端发送的请求
  11.         location /user/ {
  12.             proxy_pass   http://webservers/user/;
  13.         }
  14. }
复制代码
5、webSocket

5.1 什么是webSocket

WebSocket是基于TCP的一种新的网络协议。它实现了欣赏器与服务器全双工通信——欣赏器和服务器只必要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。
5.2、WebSocket和HTTP协议的区别?为什么不用HTTP

特性WebSocketHTTP连接性质全双工(双向实时通信)半双工(单向请求-响应)持久性长连接(创建后持续保持)短连接(默认每次请求后关闭)自动推送服务端可自动推送数据服务端只能被动响应客户端请求 这两个功能对实时性要求极高,传统的HTTP请求-响应模式无法满足毫秒级推送的需求,因此我们采用WebSocket协议实现服务端自动推送,确保商家能第一时间处置惩罚订单。
5.3 WebSocket在项目中的应用场景

我们使用WebSocket实现了两个核心功能: ✅ 来单实时提示:当用户下单并付出成功后,系统立刻关照商家端有新订单。 ✅ 客户催单处置惩罚:用户点击催单按钮后,商家端实时收到催单关照,并触发语音播报。
通过WebSocket实现管理端页面和服务端保持长连接状态。当客户付出完成大概点击催单后,调用WebSocket的相干API实现服务端向客户端推送消息,客户端欣赏器解析服务端推送的消息,判断是来单提示照旧客户催单,进行相应的消息提示和语言播报
6、SpringTask

6.1、springTask怎么实现的超时自动取消订单的功能?

Spring Task(Spring 任务调度)是 Spring 框架提供的一种任务调度框架,用于实行定时任务、异步任务、任务监听、任务调度等。
苍穹外卖采用Spring Task实现订单超时自动取消功能,核心逻辑是每分钟扫描一次数据库中订单,筛选出创建时间超过15分钟且状态为"待付出"的订单,批量修改为"已取消"状态
7、数据库相干

7.1 数据库表你是怎么设计的

序号表名1employee(员工表)2category(分类表)3dish(菜品表)4dish_flavor(菜品口胃表)5setmeal(套餐表)6setmeal_dish(套餐菜品关系表)7user(用户表)8address_book(地址表)9shopping_cart(购物车表)10orders(订单表)11order_detail(订单明细表) 7.2 为什么用逻辑外键,而不用数据库自带的外键?



  • 减少数据库开销:物理外键约束会增长数据库在插入、更新和删除操作时的额外开销。数据库必要泯灭额外的时间来检查外键约束的完备性,这在高并发、大数据量的场景下大概会对性能产生明显的影响。而逻辑外键由应用步伐来控制,开发职员可以根据具体业务场景,在必要时才进行关联数据的检查,克制了数据库层面不必要的检查操作,从而提高系统的整体性能
  • 顺应变革:在软件开发过程中,业务需求大概会不断变革。如果使用物理外键,当表布局发生变革时,例如修改外键关联的字段类型、删除关联表中的字段等操作,大概会受到外键约束的限定,导致数据库布局的修改变得复杂和困难。而逻辑外键不存在这种限定,开发职员可以更自由地对表布局进行调整,只必要在应用步伐中相应地修改逻辑外键的处置惩罚逻辑即可,提高了数据库设计的灵活性和可维护性。
8、微信相干

8.1 微信登录是怎么实现的?



  • 小步伐端,调用wx.login()获取code,就是授权码。
  • 小步伐端,调用wx.request()发送请求并携带code,请求开发者服务器(自己编写的后端服务)。
  • 开发者服务端,通过HttpClient向微信接口服务发送请求,并携带appId+appsecret+code三个参数。
  • 开发者服务端,吸收微信接口服务返回的数据,session_key+opendId等。opendId是微名誉户的唯一标识。
  • 开发者服务端,自定义登录态,天生令牌(token)和openid等数据返回给小步伐端,方便后绪请求身份校验。
  • 小步伐端,收到自定义登录态,存储storage。
  • 小步伐端,后绪通过wx.request()发起业务请求时,携带token。
  • 开发者服务端,收到请求后,通过携带的token,解析当前登录用户的id。
  • 开发者服务端,身份校验通过后,继续相干的业务逻辑处置惩罚,最终返回业务数据。
8.2怎样实现的微信付出功能?


完成微信付出有两个关键的步调:
1️⃣ 就是必要在商户系统当中调用微信背景的一个下单接口,就是天生预付出买卖业务单。
2️⃣ 就是付出成功之后微信背景会给推送消息。
9、你在项目中碰到了什么困难?

9.1处置惩罚公共字段的添补

如果都按照之前的操作方式来处置惩罚这些公共字段(创建时间,创建人id,修改时间,修改人id), 必要在每一个业务方法中进行操作, 编码相对冗余、繁琐。我们使用AOP切面编程,实现功能增强,来完成公共字段自动添补功能。
实现步调:
1). 自定义注解 AutoFill,用于标识必要进行公共字段自动添补的方法
2). 自定义切面类 AutoFillAspect,同一拦截参加了 AutoFill 注解的方法,通过反射为公共字段赋值
3). 在 Mapper 的方法上参加 AutoFill 注解

链接:
1、链接1
2、链接2
3、链接3
4、链接4
5、链接5

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

知者何南

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表