目录
设计相关
单点登录如何实现
单点登录的英文名叫做:Single Sign On(简称SSO),只要登录一次,就可以访问所有信任的应用系统。在以前的时候,一般我们就单系统,所有的功能都在同一个系统上,可以使用session共享将用户信息保存在Session对象中。后来,我们为了合理利用资源和降低耦合性,于是把单系统拆分成多个子系统。多系统即可能有多个Tomcat,而Session是依赖当前系统的Tomcat,所以系统A的Session和系统B的Session是不共享的。解决系统之间Session不共享问题有以下几种方案:
- Tomcat集群Session全局复制(最多支持5台tomcat,不推荐使用)
- JWT(常见)
- Oauth2
- CAS
- 自己实现(redis+token)
JWT参考这篇博客。使用jwt解决单点登录的流程如下:

扫码登录如何实现
扫码登录本质就是通过已经登录过的APP应用去扫描未登录的Web端的二维码,通过某种机制来触发登录凭证的写入,从而去实现Web端的自动登录这样一个过程。
首先要在网页端打开登录的页面展示一个二维码,这个二维码里有个服务端生成的唯一编号,然后浏览器会去定时轮询这个二维码的状态,然后在APP端去扫描二维码,把APP端的token信息二维码ID发送到服务端,服务店接收到请求后会去修改二维码的扫描状态,并生成一个临时的token给APP端,这个时候网页端展示的二维码状态会提示已扫描待确认,而APP端去扫码后会给用户一个确认授权的一个操作按钮,点击确认以后携带临时token到服务端,然后服务端再次修改二维码的扫码状态,并且为网页端生成授权token,最后网页端轮询到状态变化,并获取到token从而完成扫码授权。
整个过程并不难,核心设计就是一个特定的二维码去连接APP端和网页端
权限认证如何实现
后台的管理系统,更注重权限控制,最常见的就是RBAC模型来指导实现权限RBAC(Role-Based Access Control)基于角色的访问控制
- 3个基础部分组成:用户、角色、权限
- 具体实现
-
- 5张表(用户表、角色表、权限表、用户角色中间表、角色权限中间表)
-
- 7张表(用户表、角色表、权限表、菜单表、用户角色中间表、角色权限中间表、权限菜单中间表)
最常见的5张表的关系:

数据流转流程:
张三登录系统—> 查询张三拥有的角色列表—>再根据角色查询拥有的权限

在实际的开发中,也会使用权限框架完成权限功能的实现,并且设置多种粒度,常见的框架有:
- Spring security(推荐)
- Apache shiro
短链系统如何设计?
短链的原理很简单,用户访问短链的时候,短链服务器收到请求后触发302重定向,然后浏览器再请求重定向的地址,获取目标网页的内容,因此短链系统就相当于在原始链接上建立了一个映射关系,映射关系就需要考虑两个关键问题:如何生成短链?短链和长链的映射关系如何存储?
首先短链的组成有两个部分,分别是域名和长链映射的字符串,短链系统就是根据这个字符串去找到匹配的长链进行重定向,因此我们需要考虑这个映射字符串的唯一性以及长度,常见的做法就是使用哈希算法,比如MD5、SHA-1,把长链映射成一个固定长度的哈希值,但是考虑到Hash字符串的长度,我们可以进一步去选取哈希值进行64进制的转换,得到一个六位长度的值,他可以表示接近568亿的数据,应对短链的场景是完全足够的。
接下来我们可以把短链和长链的映射关系保存到数据库中,如果考虑到性能也能用redis来存储,避免后续随着数据量越来越多造成的查询性能下降问题。最后还需要考虑到Hash冲突的问题,我们可以通过再Hash法来解决,这就是关键部分的实现逻辑。
设计的更完善的话:
1.为了考虑后期的并发量过高的问题,需要设计一个能够水平扩展的系统架构。可以采用微服务架构,将不同的功能模块分解为不同的服务,比如生成短链的服务、查询长链的服务。每个服务都可以单独进行扩展;
2.为了防止恶意用户生成大量的短链,可以限制每个用户每天生成短链的数量。我们还可以使用验证码、API速率限制等手段防止机器人攻击
3.为了提高性能,可以使用CDN加速短链的访问,使用HTTP/2协议减少网络延迟,使用数据库分区和索引I优化查询速度等
4.为了更好的观察短链系统的运行情况,需搭建监控平台,包括系统性能监控、业务数据监控、异常监控。还需要记录详细的日志,包括请求日志、错误日志以便进行问题排查和性能优化
什么是CDN
中文名字叫内容分发网络,字面意思就是来做内容分发的一套网络体系,是用来提升文件下载速度的一种机制,让用户能够从离自己最近的CDN服务器进行下载,减少路由次数,提升下载速度,缩短传输时间。
打个比方,就像物流一样,北京的大仓库就相当于你的业务服务器,全国各地的分仓就相当于CDN服务器,仓储公司就是CDN服务商,货物就相当于要传输的数据,事先从大仓库分发到各地分仓,你的订单就相当于一个网络请求。
CDN服务一开始只能用于静态数据的加速,动态接口不能使用CDN服务。现代CDN除了对静态资源进行缓存加速,CDN还通过动态内容加速、链路优化、边缘计算等技术,提升整体用户体验。


CDN的基本概念
CDN,中文叫做内容分发网络,是通过将内容分布到各个节点(即边缘服务器),从而加快用户访问速度的一种技术。它的主要目的是减少延迟,提高内容的传输效率。最常见的CDN应用是静态内容的分发,例如图片、视频、CSS、JavaScript文件等。
CDN的组成部分
1.源站:源站是存储原始内容的服务器,通常位于中央数据中心。用户请求的原始内容首先来自源站。
2.边缘节点:这些是分布在全球各地的服务器,当用户请求内容时,CDN会根据用户的地理位置,将请求路由到最近的边缘节点,以提供更快的响应时间。
3.缓存策略:CDN会在边缘节点缓存源站的内容,缓存的策略可以根据内容类型、时效性等进行配置。
4.回源策略:当边缘节点没有缓存用户请求的内容时,CDN需要向源站回源获取内容。这其中涉及多种策略,例如缓存失效的更新、特定文件的强制刷新等。
动态内容加速
虽然CDN最初主要用于静态内容的加速,但现代CDN已经扩展了其能力,包括动态内容的加速。动态内容通常是根据用户请求实时生成的,例如网页中的个性化推荐内容。这种内容不能像静态内容那样简单地缓存和分发。
1.动态加速:现代CDN可以通过优化网络链路、减少跳数、使用智能路由等手段加速动态内容的传输。例如,阿里的DCDN(动态加速CDN)和Azure CDN的DSA(动态站点加速)优化就是典型的例子。
2.链路优化:通过分析和选择最优的传输路径,CDN可以减少数据在互联网中的延迟,提高传输速度。这种技术常被用于加速API请求、视频流、金融交易等需要快速响应的动态内容。
3.混合加速:一些CDN提供商将静态和动态加速结合在一起,形成混合加速服务。这可以确保用户在访问网站时,不仅能快速获取静态资源,还能快速加载动态内容。
现代CDN的发展趋势
1.边缘计算:随着物联网和5G的发展,CDN正逐渐向边缘计算演变。边缘计算通过在离用户更近的地方处理数据,进一步减少延迟。现代CDN已经开始支持在边缘节点运行代码,以处理动态内容。
2.安全性增强:CDN不再只是单纯的加速服务,还集成了DDoS防护、WAF(Web应用防火墙)等安全功能,保护网站免受网络攻击。
3.视频流优化:针对视频流的CDN优化技术也在不断发展,如HLS分片、实时转码等,确保视频在不同网络环境下都能流畅播放。
项目中有1万个if else如何优化
得分情况去处理,如果这1万个if else是在同一个代码块的流程里面,这时我们就需要考虑一下1万个ifelse存在的意义了。因为这么大量级的if else会很难维护而且极其影响性能,我们需要具体分析情况,然后再去分析如何去分解和优化。而如果这1万个if else分散在同一个项目里面那么优化if else的方式就多了:
- 0.尽快去返回。我们去具体分析这个业务,根据ifelse的执行次数来按降序排序,把执行次数较多的if放在最前面,如果条件符合就提前使用return来返回。这样改可能是比较的简单一个方式,也在很大程度上可以提升系统的性能。但是还存在一些问题,第一是有的条件不能按照执行次数排序,存在先后或者互斥的关系;第二是如果新增一个条件可能无法马上判断出它的执行次数,如果放在后面可能还会影响到性能,第三是对类的持续膨胀和代码维护也没有很大帮助
- 1.策略模式。策略模式优点很显然,既可以干掉繁琐的if else逻辑,也符合开闭原则(对扩展开放,对修改关闭。为了使程序的扩展性好,易于维护和升级),扩展性又很好,便于维护。不过也存在两个问题,如果有大量的 if else分支,比如一万个那就会有1万个策略类,此时就会造成类的膨胀,并且随着时间的一个推移逐渐变得更加庞大而复杂。而如果是多层if else嵌套的话,策略模式可能无法派上用场
- 2.策略模式变体。这种模式可以把业务逻辑代码分离出去,简化了单个类的代码,也省去了策略的实现类,让策略实现类不会得到膨胀。但是如果大量的条件映射,依然会造成单个类的膨胀和难以维护的问题。
- 3.三目运算符。如果判断条件不多,只有两到三个的情况下,可以直接使用三目运算符来简化if else的分支,不过超过3个条件就不建议使用了,不然代码的可读性会大大降低。
- 4.使用枚举类型。枚举类型可以用来表示一组固定的值,比如说星期、月份、颜色等等,它提供了一种简洁的可读性更高的方式来表示一组相关的一个常量,我们可必在枚举类属性里面去定义多个字段,这样的话就不需要大量的ifelse判断,可以直接通过枚举来直接获取某一组固定值了。
- 5.使用规则引擎。对复杂的业务逻辑,业务规则经常变化,而且规则制定可能不依赖于技术团队,需要实现可配置的逻辑处理,这时就可以考虑使用规则引擎来处理。比如说doors规则引擎可以用来执行一组规则,在许多业务系统里面,业务决策一系列的逻辑规则来定义,规则引擎允许这些规则在运行时去执行,而不需要在应用程序里面去硬编码。规则引擎的好处有很多,比如业务逻辑可以和程序代码进行解耦,提高业务逻辑的可管理性,提高系统的灵活性和可扩展性,非技术人员可以参与到决策过程中。
- 6.最后一种就是我们可以从业务逻辑层面着手,看看这些if else判断是为了解决什么问题,是否可以去从业务的设计角度去干掉这些ifelse,不过现实的项目中不太可能会有1万个ifelse代码的一个情况
规则引擎介绍见——后端开发——规则引擎简介(Drools)
金额用Long还是Bigdecimal?
首先double和float肯定排除,因为它们底层会采用科学计数法,即转换成二进制进行计算,从而导致小数点无限位的问题进而精度丢失。
Long类型在存储的时候,比如要保留小数点到分,那么存储的时候乘以100,取的时候除以100以达到效果。本质上还是一样,只不过long属于隐式小数点,而Bigdecimal属于显示小数点。
我们之前的项目因为只需要保留到分所以使用Long,但是如果项目对精确位数有要求,还是推荐在代码层面统一的使用Bigdecimal,这样方便我们进行计算,然后存储的时候用long会节省内存一点,但也是视情况而定,如果精确的位数要求特别高,那么long类型每次都要乘以很大的数,存储性能也就荡然无存了。所以如果在需求阶段无法确认小数点后面的位数或者要求小数点后面位数较多那么就用Bigdecimal来表示金额。
BigDecimal 是 Java 中一个用于处理任意精度的浮点数类,定义在 java.math 包中。与基本数据类型(如 float 和 double)相比,BigDecimal 主要用于解决由于浮点数精度问题而引起的计算不准确的问题。它特别适合于金融计算和需要高精确度的场景。
主要特点:
1.任意精度:BigDecimal 可以表示任意大小和精度的数字,允许你进行高精度的计算。
2.避免精度问题:使用 BigDecimal 可以避免浮点数在四舍五入和精度丢失方面常见的问题。
3.不可变性:BigDecimal 对象是不可变的,这意味着一旦创建,值就不能被改变。每次进行运算时,会返回一个新的 BigDecimal 对象。
4.支持四舍五入:提供了多种四舍五入策略,适合不同的应用场景。
PS:在mysql里如果java使用BigDecimal 时该用什么数据结构?
在 MySQL 中记录货币值时,通常推荐使用 DECIMAL 数据类型。这是因为货币通常要求高精度和精确的小数位数,而 DECIMAL 数据类型能够提供这种精确度。
为什么选择 DECIMAL?
● 精确度:DECIMAL 是一种定点数类型,专门设计用于存储需要高精度的小数值(如货币)。与浮点数类型(如 FLOAT 和 DOUBLE)不同,DECIMAL 不会因为二进制浮点数存储格式而引入舍入误差,因此可以准确地表示小数。
● 指定精度和标度:你可以为 DECIMAL 类型指定精度(总位数)和标度(小数点后的位数)。例如,DECIMAL(10, 2) 可以存储最多 10 位数字,其中包括 2 位小数。这使得它非常适合表示货币值。
● 适应货币运算:使用 DECIMAL 可以确保在涉及货币的加、减、乘、除运算中保持精确的结果,这对财务计算非常重要。
示例
● DECIMAL(10, 2) 表示可以存储最多 10 位数字,其中小数点后有 2 位。
● 这意味着最大值为 99,999,999.99,最小值为 -99,999,999.99。
上传数据的安全性如何保证
浏览器访问后台,需要经过网络传输,有可能会出现安全的问题。解决方案:使用非对称加密(或对称加密),给前端一个公钥让他把数据加密后传到后台,后台负责解密后处理数据
对称加密 文件加密和解密使用相同的密钥,即加密密钥也可以用作解密密钥
优点: 对称加密算法的优点是算法公开、计算量小、加密速度快、加密效率高。
缺点: 没有非对称加密安全.
用途: 一般用于保存用户手机号、身份证等敏感但能解密的信息。
常见的对称加密算法有: AES、DES、3DES、Blowfish、IDEA、RC4、RC5、RC6、HS256

非对称加密 两个密钥:公开密钥(publickey)和私有密钥,公有密钥加密,私有密钥解密。私钥隐秘保存,公钥可以下发给信任客户端.
优点: 非对称加密与对称加密相比,其安全性更好;
缺点: 非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。
用途: 一般用于签名和认证。私钥服务器保存, 用来加密, 公钥客户拿着用于对于令牌或者签名的解密或者校验使用.
常见的非对称加密算法有: RSA、DSA(数字签名用)、ECC(移动设备用)、RS256 (采用SHA-256 的 RSA 签名)

订单表每天新增500W数据,分库分表的方案应该如何设计
分库分表的方案 要避免分好之后又出现容量满的情况或者单表数据过大的问题,这个时候再去做容量扩充那么数据迁移和扩容的成本会很高。
一天500w,那么一年大概有18亿的数据,按照保留两年的热数据量大概是40亿,再做一些空间预留算50亿。那么可以按照32个库,每个库32个表来规划,一共1024张表,每张表500w的数据,便可以满足50亿的数据规划。在这个方案中我们可以选择orderID作为分片键,采用一致性哈希算法来路由。
在性能层面假设每个库正常写入的并发量是1000,那32个库可以承载32000的并发量。如果每个库的写性能再优化到1500,就意味着这个方案能支持接近5w每秒的写并发
需要考虑的其他问题
业务需要根据用户id查找,而用户id不是分片键导致查找复杂怎么解决?
- 我们可以采用基因算法确保用户id对应的订单id路由到同一个库或者同一个表,在生成订单ID的时候把用户ID的基因片段拼接到订单ID中,从而保证不管是通过订单ID还是用户ID都能路由到同一个表。
虽然设计了1024个表,但也只能存储50亿的数据,也就只能存储三年的数据,三年后方案就不满足了怎么解决?
- 订单这种业务我们频繁访问的数据一般在一年以内,超过一年的数据基本上不用关系了,可以设计冷热数据分离的方案。热数据保特一年,一年以内的数据迁移到历史库。历史库也就是冷库只保存2年,超过这个时间的数据直接归档,从而实现一个1+2的存储方案
还有什么其他的存储方案可以采用的么?
- 可以采取如今比较主流的HTAP存储方案,比如TiDB、PolorDB等等,这类数据库的好处是可以支持在线扩容,比如分片、迁移这种扩展对业务完全无感知,同时支持强一致性分布事务的方案,也就是跨分片跨节点的事务一致性,可以跨机房部署实现跨机房容灾,支持多节点写入。
分布式锁有哪些实现方案?
第一种,通过redis实现,参考Redis相关。
第二种,通过ZooKeeper实现。
关于分布式锁这个问题不管用什么技术锁的本质是不变的,如果是排他锁意外着在同一时刻只有一个线程或进程拿到锁资源,获得访问权限,基于这样一个点去推演ZooKeeper怎么达到这个目的就行了。ZooKeeper学习可以参考这篇文章。
而ZooKeeper的结构类似于一个具有层次关系的文件系统,每一个节点代表一个k-v结构的数据,这些节点有几个重要特性:1.同一级节点不能存在重复的数据;2.提供了有序节点的特性,可以根据创建的先后分配一个有序的编号。这种特性是实现分布式锁的关键。
问题回答:我们可以用到ZooKeeper里面的有序节点来实现分布式锁。具体实现的过程是
- 1.在ZooKeeper上去创建一个持久化的节点,比如叫/exclusive_lock作为锁的根节点
本文详细探讨了Java后端开发中遇到的各种场景问题,包括单点登录的实现、权限认证的策略、数据安全的保证、海量数据的分库分表设计、分布式锁的实现方式、Mybatis分页查询、多并发下的秒杀场景处理、限流算法的比较、下单接口中防止超卖的措施、订单支付超时的解决方案、接口幂等性和防重放的保障,以及雪花算法的原理。此外,还介绍了项目日志采集、问题排查和系统瓶颈定位的方法。
最低0.47元/天 解锁文章
1万+

被折叠的 条评论
为什么被折叠?



