自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(31)
  • 资源 (1)
  • 收藏
  • 关注

原创 函数式编程

函数式编程有很多种定义很多种特性,这里从架构的角度,只关注它的没有副作用和不修改状态。函数式编程中,函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。在架构领域所有的竞争问题、死锁问题、并发问题都是由可变变量导致的。如果有足够大的存储量和计算量,应用程序可以用事件溯源的方式,用完全不可变的函数式编程,只通过事务记录从头计算状态,就避免了前面提到的几个问题。要让一个软件系统完全没有可变变量是不现实的,但是可以通过将需要修改状态的部分和不需要修改的部分分隔成单独的

2021-02-06 19:54:59 129

原创 数据处理

客户端的计算不可信。虽然目前很多项目的前端都是富前端,会做大量的逻辑计算,无需访问服务端接口就可以顺畅完成各种功能,但来自客户端的计算结果不能直接信任。最终在进行业务操作时,客户端只能扮演信息收集的角色,虽然可以将诸如价格等信息传给服务端,但只能用于校对比较,最终要以服务端的计算结果为准。 所有来自客户端的参数都需要校验判断合法性。即使知道用户是在一个下拉列表选择数据,即使我们知道用户通过网页正常操作不可能提交不合法的值,服务端也应该进行参数校验,防止非法用户绕过浏览器 UI 页面通过工具直接向服务端提交

2021-01-31 20:32:59 170

原创 反射、注解和泛型

反射调用方法并不是通过调用时的传参确定方法重载,而是在获取方法的时候通过方法名和参数类型来确定的。遇到方法有包装类型和基本类型重载的时候。 反射获取类成员,需要注意 getXXX 和 getDeclaredXXX 方法的区别,其中 XXX 包括 Methods、Fields、Constructors、Annotations。这两类方法,针对不同的成员类型 XXX 和对象,在实现上都有一些细节差异,详情请查看官方文档。今天提到的 getDeclaredMethods 方法无法获得父类定义的方法,而 g...

2021-01-24 22:23:39 113

原创 时间类处理

使用 Java 8 中的日期时间包 Java.time 的类进行各种操作,会比使用遗留的 Date、Calender 和 SimpleDateFormat 更简单、清晰,功能也更丰富、坑也比较少。 在把 Date 转换为 LocalDateTime 的时候,需要通过 Date 的 toInstant 方法得到一个 UTC 时间戳进行转换,并需要提供当前的时区,这样才能把 UTC 时间转换为本地日期时间(的表示) 把 LocalDateTime 的时间表示转换为 Date 时,也需要提供时区,用于指...

2021-01-17 22:45:27 71

原创 缓存设计

缓存设计不能把诸如 Redis 的缓存数据库完全当作数据库来使用。不能假设缓存始终可靠,也不能假设没有过期的数据必然可以被读取到,需要处理好缓存的回源逻辑;而且要显式设置 Redis 的最大内存使用和数据淘汰策略,避免出现 OOM 的问题。 缓存的性能比数据库好很多,需要考虑大量请求绕过缓存直击数据库造成数据库瘫痪的各种情况。对于缓存瞬时大面积失效的缓存雪崩问题,可以通过差异化缓存过期时间解决;对于高并发的缓存 Key 回源问题,可以使用锁来限制回源并发数;对于不存在的数据穿透缓存的问题,可以通过布隆

2021-01-10 11:26:13 131

原创 敏感数据

敏感数据用户密码不能加密保存,更不能明文保存,需要使用全球唯一的、具有一定长度的、随机的盐,配合单向散列算法保存。 使用 BCrypt 算法,是一个比较好的实践。诸如姓名和身份证这种需要可逆解密查询的敏感信息,需要使用对称加密算法保存。把脱敏数据和密文保存在业务数据库,独立使用加密服务来做数据加解密 对称加密需要用到的密钥和初始化向量,可以和业务数据库分开保存 对于数据传输,则务必通过 SSL/TLS 进行传输。对于用于客户端到服务端传输数据的 HTTP,需要使用基于 SSL/TLS 的 HTTP

2021-01-03 23:07:54 575 1

原创 解决代码重复

解决代码重复利用工厂模式 + 模板方法模式,消除 if…else 和重复代码,有多个并行的类实现相似的代码逻辑。可以考虑提取相同逻辑在父类中实现,差异逻辑通过抽象方法留给子类实现。使用类似的模板方法把相同的流程和逻辑固定成模板,保留差异的同时尽可能避免代码重复。同时,可以使用 Spring 的 IoC 特性注入相应的子类,来避免实例化子类时的大量 if…else 代码。 使用硬编码的方式重复实现相同的数据处理算法。可以考虑把规则转换为自定义注解,作为元数据对类或对字段、方法进行描述,然后通过反射动态读

2020-12-27 21:26:37 842

原创 OOM

程序确实需要超出 JVM 配置的内存上限的内存。不管是程序实现的不合理,还是因为各种框架对数据的重复处理、加工和转换,相同的数据在内存中不一定只占用一份空间。针对内存量使用超大的业务逻辑,比如缓存逻辑、文件上传下载和导出逻辑,我们在做容量评估时,可能还需要实际做一下 Dump,而不是进行简单的假设。出现内存泄露,其实就是认为没有用的对象最终会被 GC,但却没有。GC 并不会回收强引用对象,可能经常在程序中定义一些容器作为缓存,但如果容器中的数据无限增长,要特别小心最终会导致 OOM。使用 WeakHash

2020-12-20 19:59:01 154

原创 2020-12-13

数值计算使用 BigDecimal 表示和计算浮点数,且务必使用字符串的构造方法来初始化 BigDecimal:要精确表示浮点数应该使用 BigDecimal。并且,使用 BigDecimal 的 Double 入参的构造方法同样存在精度丢失问题,应该使用 String 入参的构造方法或者 BigDecimal.valueOf 方法来初始化。 System.out.println(new BigDecimal("0.1").add(new BigDecimal("0.2"))); S.

2020-12-13 23:13:20 176

原创 异步处理

异步处理要考虑异步流程丢消息或处理中断的情况,异步流程需要有备线进行补偿。比如全量补偿方式,即便异步流程彻底失效,通过补偿也能让业务继续进行。 异步处理的时候需要考虑消息重复的可能性,处理逻辑需要实现幂等,防止重复处理。 微服务场景下不同服务多个实例监听消息的情况,一般不同服务需要同时收到相同的消息,而相同服务的多个实例只需要轮询接收消息。我们需要确认 MQ 的消息路由配置是否满足需求,以避免消息重复或漏发问题。 要注意始终无法处理的死信消息,可能会引发堵塞 MQ 的问题。一般在遇到消息处理失败的

2020-12-06 16:01:41 131

原创 null和空指针处理

null和空指针处理针对判空,通过 Optional 配合 Stream 可以避免大多数冗长的 if-else 判空逻辑,实现一行代码优雅判空。另外,要定位和修复空指针异常,除了可以通过增加日志进行排查外,在生产上使用 Arthas 来查看方法的调用栈和入参会更快捷。 业务系统最基本的标准是不能出现未处理的空指针异常,因为它往往代表了业务逻辑的中断,所以我建议每天查询一次生产日志来排查空指针异常,有条件的话建议订阅空指针异常报警,以便及时发现及时处理。 POJO 中字段的 null 定位,从服务端的

2020-11-28 11:15:10 399

原创 数据库连接

连接超时代表建立 TCP 连接的时间,读取超时代表了等待远端返回数据的时间,也包括远端程序处理的时间。 在解决连接超时问题时,要搞清楚连的是谁;在遇到读取超时问题的时候,要综合考虑下游服务的服务标准和自己的服务标准,设置合适的读取超时时间。此外,在使用诸如 Spring Cloud Feign 等框架时务必确认,连接和读取超时参数的配置是否正确生效。 因为 HTTP 协议认为 Get 请求是数据查询操作,是无状态的,又考虑到网络出现丢包是比较常见的事情,有些 HTTP 客户端或代理服务器会自动重试 Ge

2020-11-22 23:02:13 90

原创 数据相关

数据代码要从根本上、从最底层进行堵漏,尽量不要在高层框架层面做,否则堵漏可能不彻底。 堵漏要同时考虑进和出,不仅要确保数据存入数据库的时候进行了转义或过滤,还要在取出数据呈现的时候再次转义,确保万无一失。 除了直接堵漏外,还可以通过一些额外的手段限制漏洞的威力。比如,为 Cookie 设置 HttpOnly 属性,来防止数据被脚本读取;又比如,尽可能限制字段的最大保存长度,即使出现漏洞,也会因为长度问题限制黑客构造复杂攻击脚本的能力。敏感数据用户密码不能加密保存,更不能明文保存,需要使用全球唯

2020-11-15 22:47:12 257

原创 连接池学习

极客时间学习笔记连接池业务代码最常用的 Redis 连接池、HTTP 连接池、数据库连接池 客户端 SDK 实现连接池的方式,包括池和连接分离、内部带有连接池和非连接池三种。要正确使用连接池,就必须首先鉴别连接池的实现方式。比如,Jedis 的 API 实现的是池和连接分离的方式,而 Apache HttpClient 是内置连接池的 API。 鉴别客户端 SDK 是否基于连接池。TCP 是面向连接的基于字节流的协议:面向连接,意味着连接需要先创建再使用,创建连接的三次握手有一定开销;基于字.

2020-11-08 21:53:34 161

原创 ddd实体与值对象

​ Entity(实体): 每个实体是唯一的,并且可以相当长的一段时间内持续地变化。我们可以对实体做多次修改,故一个实体对象可能和它先前的状态大不相同。但是,由于它们拥有相同的身份标识,他们依然是同一个实体。例如一件商品在电商商品上下文中是一个实体,通过商品中台唯一的商品id来标示这个实体。​ ValueObject(值对象):值对象用于度量和描述事物,当你只关心某个对象的属性时,该对象便可作为一个值对象。实体与值对象的区别在于唯一的身份标识和可变性。当一个对象用于描述一个事物,但是又没有唯一标示,那么

2020-11-01 22:10:54 705

原创 性能瓶颈因素

极客时间学习笔记(1)代码层面做好工作:减少磁盘I/O操作、降低竞争锁的使用以及使用高效的算法等等;(2)比较复杂的业务,可以充分利用设计模式来优化业务代码。例如,设计商品价格的时候,往往会有很多折扣活动、红包活动,可以用装饰模式去设计;(3)编码完成之后进行性能测试,项目成功上线后,还需要根据线上的实际情况,依照日志监控以及性能统计日志,来观测系统性能问题;衡量性能指标衡量系统的性能指标有:响应时间、吞吐量、计算机资源分配使用率、负载承受能力。(1)响应时间,分为以...

2020-10-25 10:08:55 262

原创 DDD聚合

极客时间学习笔记(1)聚合根内会定义引用的实体,在聚合根内部直接使用引用的实体属性或者方法,这些实体的方法会被封装成领域服务或者应用服务,外界不需要关心这些实体内的属性或者方法实现;(2)限界上下文是在分析并找出所有聚合后,将在同一个语义环境下的多个聚合组成限界上下文,也可以理解为完成同一个业务功能模块,它本质上就是子域;(3)DDD领域建模优先,领域建模的时基本不考虑数据模型和数据库实现。在微服务具体落地的时候才考虑数据实体的设计。(4)聚合内的实体数据维护是聚合根通过仓储来统一维.

2020-10-17 21:04:44 359

原创 DDD领域驱动设计

极客时间学习笔记为什么微服务设计的时候需要DDD?(1)软件架构模式演进的三个阶段:第一阶段是单机架构;第二阶段是集中式架构;第三阶段是分布式微服务架构;(2)在单机和集中式架构这两种模式下,软件无法快速响应需求和业务的迅速变化,最终错失发展良机。(3)微服务拆分困境产生的根本原因就是不知道业务或者微服务的边界到底在什么地方。(4)DDD 核心思想是通过领域驱动设计方法定义领域模型,从而确定业务和应用边界,保证业...

2020-10-11 12:27:18 229

原创 数据库及缓存相关

《极客时间》学习笔记如何搭建高性能、高可用的MySQL架构主从同步:数据冗余、集群搭建、数据备份; 读写分离:减少加锁、提高读写效率; 分库分表:数据表扩容、专库专用、垂直拆分; 数据库优化:慢SQL查询、SQL执行计划; 去中心化:心跳机制、虚拟IP、防止单点灾难。多级缓存的实现双写优势,多个数据表可以异构到一个表若采用MQ或binlog则只能通过监听订单表,并再异构时反查数据库获取订单详情表数据,才能实现完整的数据异构,不仅增加数据库查询压力也增加了复...

2020-09-26 15:53:32 186

原创 支付系统中有那些技术问题可能会引发资金损失

《极客时间》学习笔记网络问题网络一层一般进去catch处理,走失败分支,银行可能是成功、失败、处理中,若是成功商户再发起就会重复扣款方案:设置为处理中状态,等待定时查询或通知返回最终状态2、查询和通知问题(1)查询失败、查询异常不代表交易最终是失败的,特别是第三方查询交易接口返回失败,这是订单查询失败,不是交易本身失败,若误设置为订单失败,则可能引发重复扣款(2)查询频率过快,第三方还没处理好,查询无订单(3)被查询接口幂等性问题,银行T+1和T状态不一样(4)通知:..

2020-09-20 22:56:03 523

原创 缓存

学习极客时间《后端技术38讲》笔记,学习了缓存相关内容:(1)缓存可以分成两种,通读缓存和旁路缓存;(2)通读缓存:应用程序访问通读缓存获取数据的时,如果通读缓存有需要的数据则返回;如果没有,那么通读缓存访问数据源,从数据源获取数据返回给应用程序,并将这个数据缓存在自己的缓存中。互联网应用中主要使用的通读缓存是 CDN 和反向代理缓存;(3)旁路缓存,应用程序访问旁路缓存获取数据的时,如果旁路缓存中有应用程序需要的数据就返回;如果没有就返回空null。应用程序需要自己从数据源读取数据,然后将这个

2020-09-13 09:34:53 165

原创 后端技术38讲学习笔记day

极客时间《后端技术38讲》学习笔记设计模式开闭原则(1)开闭原则:软件功能可以扩展,但是软件实体不可以被修改。实现开闭原则的关键是抽象;(2)策略模式实现开闭原则:多个策略实现同一个策略接口,根据不同上下文传入不同的策略实现;(3)适配器模式实现开闭原则:适配器模式是一种结构模式,将两个不匹配的接口适配起来,解决两个接口同时实现开闭原则;(4)观察者模式实现开闭原则:解决一对多的对象依赖关系,将抽象作为被观察者对象,并将其行为通知到多个观察者;(5)模板方法模式实现开闭原则:将需扩展

2020-09-05 16:39:19 201

原创 性能调优之上下文切换

极客时间,java性能调优 学习笔记(1)TCP长连接+Protobuf序列化实现的RPC,性能要明显优于短连接的Http+Json序列化的RPC性能;(2)偏向锁主要用来优化同一线程多次申请同一个锁的竞争,当一个线程再次访问这个同步代码或方法时,该线程只需去对象头的Mark Word中去判断一下是否有偏向锁指向它的ID,无需再进入Monitor去竞争对象了;(3)Lock锁的基本操作是通过乐观锁来实现的,但由于Lock锁也会在阻塞时被挂起,因此它依然属于悲观锁;(...

2020-08-30 23:04:28 237

原创 serialVersionUID

serialVersionUID序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,将数据分解成字节流,以便存储在文件中或在网络上传输。有两种初始化方式:默认的1L,比如:private static final long serialVersionUID = 1L; 根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段private static final long serialVersionUID = -8940196742313994740L;serial

2020-08-23 22:33:39 128

原创 生产问题分析定位

极客时间《Java业务开发常见错误100例》学习笔记生产问题分析定位分析问题一定是需要依据的,靠猜是猜不出来的,需要提前做好基础监控的建设。监控的话,需要在基础运维层、应用层、业务层等多个层次进行。定位问题的时候,同样需要参照多个监控层的指标表现综合分析。 定位问题要先对原因进行大致分类,比如是内部问题还是外部问题、CPU 相关问题还是内存相关问题、仅仅是 A 接口的问题还是整个应用的问题,然后再去进一步细化探索,一定是从大到小来思考问题;在追查问题遇到瓶颈的时候,可以先退出细节,再从大的方面捋.

2020-08-16 22:04:12 289

原创 数据存储、数据源头、安全问题、数据代码、敏感数据

极客时间《Java业务开发常见错误100例》学习笔记数据存储Redis 对单条数据的读取性能远远高于 MySQL,但不适合进行范围搜索。 InfluxDB 对于时间序列数据的聚合效率远远高于 MySQL,但因为没有主键,所以不是一个通用数据库。 ES 对关键字的全文搜索能力远远高于 MySQL,但是字段的更新效率较低,不适合保存频繁更新的数据。 主数据由两种 MySQL 数据表构成,其中索引表承担简单条件的搜索来得到主键,Sharding 表承担大并发的主键查询。主数据由同步写服务写入,写入.

2020-08-09 10:45:33 502

原创 代码重复、接口设计、缓存设计、生产就绪、异步处理常见问题

极客时间《Java业务开发常见错误100例》学习笔记解决代码重复利用工厂模式 + 模板方法模式,消除 if…else 和重复代码,有多个并行的类实现相似的代码逻辑。我们、、可以考虑提取相同逻辑在父类中实现,差异逻辑通过抽象方法留给子类实现。使用类似的模板方法把相同的流程和逻辑固定成模板,保留差异的同时尽可能避免代码重复。同时,可以使用 Spring 的 IoC 特性注入相应的子类,来避免实例化子类时的大量 if…else 代码。 使用硬编码的方式重复实现相同的数据处理算法。可以考虑把规则转换为自.

2020-08-01 21:26:58 272

原创 序列化、时间类、OOM、反射注解、Spring框架常见问题

极客时间《Java业务开发常见错误100例》学习笔记序列化操作要确保序列化和反序列化算法的一致性。因为,不同序列化算法输出必定不同,要正确处理序列化后的数据就要使用相同的反序列化算法。 Jackson 有大量的序列化和反序列化特性,可以用来微调序列化和反序列化的细节。需要注意的是,如果自定义 ObjectMapper 的 Bean,小心不要和 Spring Boot 自动配置的 Bean 冲突。 在调试序列化反序列化问题时,一定要捋清楚三点:是哪个组件在做序列化反序列化、整个过程有几次序列化反.

2020-07-25 20:10:39 268

原创 集合、空值处理、异常处理、日志、文件IO常见开发问题

极客时间《Java业务开发常见错误100例》学习笔记List列表操作常见坑Arrays.asList 得到的是 Arrays 的内部类 ArrayList,List.subList 得到的是 ArrayList 的内部类 SubList,不能把这两个内部类转换为 ArrayList 使用。 Arrays.asList 直接使用了原始数组,可以认为是共享“存储”,而且不支持增删元素; List.subList 直接引用了原始的 List,也可以认为是共享“存储”,而且对原始 List 直接进行结.

2020-07-19 23:04:20 210

原创 http调用、Spring声明式事务、数据库索引、判等问题、数值计算

极客时间《Java业务开发常见错误100例》学习笔记HTTP 调用最常遇到的超时、重试和并发问题连接超时代表建立 TCP 连接的时间,读取超时代表了等待远端返回数据的时间,也包括远端程序处理的时间。 在解决连接超时问题时,要搞清楚连的是谁;在遇到读取超时问题的时候,要综合考虑下游服务的服务标准和自己的服务标准,设置合适的读取超时时间。此外,在使用诸如 Spring Cloud Feign 等框架时务必确认,连接和读取超时参数的配置是否正确生效。 因为 HTTP 协议认为 Get 请求是数据查询.

2020-07-13 09:15:10 270

原创 并发工具、代码加锁、线程池、连接池开发常见问题

1. 线程重用导致信息错乱ThreadLocal 用于变量在线程间隔离,而在方法或类间共享的场景

2020-07-05 21:21:36 486

九格宫日记网站源码

Java web+ajax+jQuery+MySql

2017-05-02

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除