前言 池化思想在实际开发中有很多应用,指的是针对一些创建成本高,创建频繁的对象,用完不弃,将其缓存在对象池子里,下次使用时优先从池子里获取,如果获取到则可以直接使用,以此降低创建对象的开销。我们最熟悉的数据库连接池就是一种池化思想的应用,数据库操作是非常频繁的,数据库连接的创建、销毁开销很大,每次都需要进行TCP三次握手和四次挥手,权限检查等,所以如果每次操作数据库都重新创建连接,用完就丢弃,对于应用程序来说是不可接受的。在java世界里,一切皆对象,所以需要有一个数据库对象连接池,用于保存连接池对象。例如使用hikari,可以配置spring.datasource.hikari.maximu...

  Tby6ZQEZbqi9   2024年03月15日   34   0   0 Java

前言 关于动态代理的一些知识,以及cglib与jdk动态代理的区别,在这一篇已经介绍过,不熟悉的可以先看下。本篇我们来学习一下cglib的FastClass机制,这是cglib与jdk动态代理的一个主要区别,也是一个面试考点。我们知道jdk动态代理是使用InvocationHandler接口,在invoke方法内,可以使用Method方法对象进行反射调用,反射的一个最大问题是性能较低,cglib就是通过使用FastClass来优化反射调用,提升性能,接下来我们就看下它是如何实现的。 示例 我们先写一个helloworld,让代码跑起来。如下: publicclassHelloWorld{ ...

  Tby6ZQEZbqi9   2024年03月12日   32   0   0 Java

背景 由于业务变迁,合规要求,我们需要删除大量非本公司的数据,涉及到上百张表,几个T的数据清洗。我们的做法是先从基础数据出发,将要删除的数据id收集到一张表,然后再由上往下删除子表,多线程并发处理。我们使用的是阿里的polardb,完全兼容mysql协议,5.7版本,RC隔离级别。删除过程一直很顺利,突然有一天报了大量:“Lockwaittimeoutexceeded;tryrestartingtransaction”。从日志上看是获取锁失败了,马上想到出现死锁了,但我们使用RC,这个隔离级别下会出现不可重复读和幻读,但没有间隙锁等,并发效率比较高,在我们实际应用过程中,也很少遇到加锁失败的问...

  Tby6ZQEZbqi9   2023年12月26日   32   0   0 MySQL

背景 阿里java开发规范是阿里巴巴总结多年来的最佳编程实践,其中每一条规范都经过仔细打磨或踩坑而来,目的是为社区提供一份最佳编程规范,提升代码质量,减少bug。这基本也是java业界都认可的开发规范,我们团队也是以此规范为基础,在结合实际情况,补充完善。最近在团队遇到的几个问题,加深了我对这份开发规范中几个点的理解,下面就一一道来。 日志规约 这条规范说明了,在异常发送记录日志时,要记录案发现场信息和异常堆栈信息,不处理要往上throws,切勿吃掉异常。堆栈信息比较好理解,就是把整个方法调用链打印出来,方便定位具体是哪个方法出错。而案发现场信息我认为至少要能说明:“谁发生了什么错误”。例如...

  Tby6ZQEZbqi9   2023年12月04日   33   0   0 Java

背景 在我们系统中有这么一个需求,业务方会通过mq将一些用户信息传给我们,我们的服务处理完后,再将信息转发给子系统。mq的内容如下: @Data publicclassPerson{ //第一部分 privateIntegercountryId; privateIntegercompanyId; privateStringuid; //第二部分 privateUseruserBaseInfo; privateList<UserContact>contactList; privateList<UserAddress>addressList; privateUserEd...

  Tby6ZQEZbqi9   2023年11月02日   39   0   0 Java

简介 限流顾名思义是对流量大小进行限制,防止请求数量超过系统的负载能力,导致系统崩溃,起到保护作用。现实生活中限流也随处可见,节假日出门旅行的人数会剧增,对于旅游景点来说往往会不堪重负,如果不进行人数控制,对整个景点的压力会非常大,游客的体验也会非常差,还容易出现安全事故等危险。同样的在一线城市地铁限流也非常常见,早高峰为了控制乘车人数和有序进站,地铁往往会在地铁口进行拦截,一定时间内才放行一部分人进站乘车。 具体到程序,限流可以有以下几种场景 限制某个接口每秒最多访问多少次 限制某个ip每秒最多访问多少次 限制某个用户或某个来源每秒最多访问多少次 限制某些用户下载速度每秒最多多少kb 禁止...

  Tby6ZQEZbqi9   2023年11月01日   66   0   0 Java

前言 现有主流消息中间件都是生产者-消费者模型,主要角色都是:Producer->Broker->Consumer,上手起来非常简单,但仍有需要知识点需要我们关注,才能避免一些错误的使用情况,或者使用起来更加高效,例如本篇要讲的kafka分区分配策略。在开始前我们先简单回顾一下kafka消息存储设计,如下图: topic是一个逻辑概念,一个topic可以包含多个partition,partition才是物理概念,kafka将partition存储在broker磁盘上。如图,test_topic只有一个partition,那么在broker上就会一个test_topic-0的文件夹。...

  Tby6ZQEZbqi9   2023年11月01日   77   0   0 Java

随着时间推移,参与开发的人员越来越多,项目代码也会越来越复杂,需要我们有意识的定期对代码进行优化,有问题及时解决,避免技术债务越积越多。这不本人就遇到一个服务启动慢的问题,印象中服务启动是比较快的,一般也就20几秒,但这次开发一个需求发现服务启动要接近1分钟,这对本地开发调试,测试同学测试都是非常不方便的,影响工作效率。 启动服务后观察日志,发现在最后一行这里卡了好久,但没有更有帮助的日志信息打印正在做什么。从图看起来像是xxljob的问题,但这是很早就引入了的,以前启动并不会慢,通过打断点也可以看出xxljob的初始化并没有阻塞。 一般服务启动慢原因主要有:1.程序太大了,加载的bean非...

  Tby6ZQEZbqi9   2023年11月01日   70   0   0 Java

问题描述 分享一个发版过程服务报错问题,问题出现在每次发版,服务准备下线的时候,报错的位置是在将任务submit提交给线程池,使用Future.get()引发的TimeoutException,错误日志会打印下面的"error"。伪代码如下: List<Future<Result<List<InfoVO>>>>futures=newArrayList<>(); lists.forEach(item->{ futures.add(enhanceExecutor.submit(()->feignClient.getTime...

  Tby6ZQEZbqi9   2023年11月01日   88   0   0 Java

前言 为了更好的进行开发和维护,我们都会对程序进行分层设计,例如常见的三层,四层,每层各司其职,相互配合。也随着分层,出现了VO,BO,PO,DTO,每层都会处理自己的数据对象,然后向上传递,这就避免不了经常要将一个对象的属性拷贝给另一个对象。 例如我有一个User对象和一个UserVO对象,要将User对象的10个属性赋值个UserVo的同名属性:一种方式是手写,一个属性一个属性赋值,相信大家最开始学习时都是这么干的,这种方式就是太低效了。在idea中可以安装插件帮我们快速生成set属性代码,虽然还是逐个属性赋值,但比一个个敲,效率提高了很多。 上面两种方式虽然最原始,做起来很麻烦,容易出错...

  Tby6ZQEZbqi9   2023年11月01日   399   0   0 Java

要解决多线程并发问题,常见的手段无非就几种。加锁,如使用synchronized,ReentrantLock,加锁可以限制资源只能被一个线程访问;CAS机制,如AtomicInterger,AtomicBoolean等原子类,通过自旋的方式来尝试修改资源;还有本次我们要介绍的ThreadLocal类,通过为每个线程维护一个变量副本,每个线程都有自己的资源了,自然没有并发问题。ThreadLocal也是一个高频面试题,看下如下的问题,是否没想象中那么简单呢,看完这篇文章以后面试再问ThreadLocal就毫无鸭梨了。 ThreadLocal作用,原理 你在哪些场景使用过ThreadLocal,...

  Tby6ZQEZbqi9   2023年11月01日   79   0   0 Java

前言 在面试这一篇我们介绍过CountDownLatch和CyclicBarrier,它们都是jdk1.5提供的多线程并发控制类,内部都是用AQS这个同步框架实现。在我们的实际项目中,有很多场景是需要从数据库查询一批数据,多线池执行某些操作,并且要统计结果,我们对这个过程做了一些封装,由于要统计结果,所以需要等所有任务都处理完成,我们用到了CountDownLatch实现同步。伪代码如下: ExecuteInstanceei=ExecuteInstance.build(myExecutor);//线程池 //循环 LoopShutdown.build("myTask").loop(()-...

  Tby6ZQEZbqi9   2023年11月01日   39   0   0 Java

前言 不知道大家有没有发现,设计模式学习起来其实不容易,并不是说它难,主要是它表达的是思想层面或者说抽象层面的东西,如果你没有实践经历过,感觉就是看了就懂,过了就忘。所以本人现在也不多花费时间去专门学习设计模式,而是平时在看一些框架源码时,多留意,多学习别人的设计方法和实现思路,在平时工作中,遇到比较复杂的场景,不好看的代码,或者想要更优雅的写法时,再反过来去翻设计模式,这样学习起来印象更加深刻,出去面试时,有解决场景也比背书要更容易说服别人。 这不最近在review同学代码时就发现如下代码,学习的机会不就来了吗 我简单说一下这段代码的逻辑,非常简单,就是要处理客户端上传的一批数据,处理前要校...

  Tby6ZQEZbqi9   2023年11月01日   72   0   0 Java

前言 "redis是单线程的"这句话我们耳熟能详。但它有一定的前提,redis整个服务不可能只用到一个线程完成所有工作,它还有持久化、key过期删除、集群管理等其它模块,redis会通过fork子进程或开启额外的线程去处理。所谓的单线程是指从网络连接(accept)->读取请求内容(read)->执行命令->响应内容(write),这整个过程是由一个线程完成的,至于为什么redis要设计为单线程,主要有以下原因: 基于内存。redis命令操作主要都是基于内存,这已经足够快,不需要借助多线程。 高效的数据结构。redis底层提供了动态简单动态字符串(SDS)、跳表(skipl...

  Tby6ZQEZbqi9   2023年11月01日   43   0   0 NoSQL

前言 本篇来介绍一下redispipeline,主要是由于最近一次在帮开发同学review代码的时候,发现对redis有个循环操作可以优化。场景大概是这样的,根据某个uid要从redis查询一批数据,每次大概1000个key左右,如果查得到就返回,否则查db,然后写回缓存。由于每次要查的key比较多,虽然redis单次查询很快,但如果key很多,每次查询redis都需要读写socket,与client间的网络数据传输,都需要消耗时间,累加起来也会变得非常慢。开发同学决定使用批量的方式,例如每次操作100个key,使用RedisTemplate批量查询代码如下: redisTemplate.op...

  Tby6ZQEZbqi9   2023年11月01日   53   0   0 NoSQL

背景 生产上有个导报表功能,工作了很长一段时间一直都很稳,没出现过什么问题,最近运营同学突然反馈导出来的数据和实际的对不上,经过排查发现导出的数据有重复,也有的没导出来。由于我们提前生成好数据(每天会truncate重新生成),所以导出的逻辑非常简单,不需要关联很多表捞数据,只需要从一张表查即可,这个表的数据量不大,发生问题时7800条左右,查询的sql也非常简单,可以选择条件导出知道时间段的数据,如下: SELECTFROMt_reportWHERErepayment_time>1622390400000ANDrepayment_time<=1624032000000limit1...

  Tby6ZQEZbqi9   2023年11月01日   122   0   0 MySQL
关注 更多

空空如也 ~ ~

粉丝 更多

空空如也 ~ ~