- 博客(47)
- 资源 (1)
- 收藏
- 关注
原创 利用mybatis插件开发动态更改sql
1、业务背景需求目前楼主所在公司线上与预发环境用的是同一套数据库,这样做的目的是在预发环境验收线上的真实情况。但是有几个配置表需要单独在预发环境更改,如果更改了会影响到线上用户使用,所以如何将配置表做环境隔离,在不更改现有代码的情况下;做法就是利用mybatis提供的插件开发机制对底层的4大内置对象进行拦截;那么4大内置对象都有哪些?2、4大内置对象Executor:代表执行器,由它调度StatementHandler、ParameterHandler、ResultSetHandler等来执行对
2021-09-26 18:33:45 1525
原创 分布式事务解决方案、技术选型
一、基本概念1、什么是事务事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败。2、本地事物在计算机系统中,更多的是通过关系型数据库来控制事务,这是利用数据库本身的事务特性来实现的,因此叫数据库事务,由于应用主要靠关系数据库来控制事务,而数据库通常和应用在同一个服务器,所以基于关系型数据库的事务又被称为本地事务。数据库事务的四大特性:ACID原子性(Atomicity),可以理解为一个事务内的所有操作要么都执行,要么...
2021-08-31 11:52:12 592
原创 线上压测、系统性能优化
前提:最近公司在搞活动,预计会来一波业务高峰,流量会达到平时的6倍,所以各个系统都在优化、压测。目前我所负责的系统为支付系统,也就是整个链路的最下游,目前支付系统单节点TPS峰值150,10个节点,压测目标是3000+,这差了将近2倍,基于此背景下开始各种优化优化先从代码上优化,主要的优化点有:1、整个支付链路涉及到调用外部接口的地,全部异步处理,等支付完成在处理。(如果不是支付时必要的参数)2、对一些配置表的读取增加了缓存3、数据库连接从10改成了30,数据库使用的是polardb(阿里云的
2021-04-09 23:20:43 607
原创 线上慢sql排查
背景:随着业务量上升,数据量越来越大,今天sql监控平台预警出一条慢sql,耗时约2.8s左右,如下:SELECT * FROM table_a WHERE create_time BETWEEN '2021-03-04 17:10:00' AND '2021-04-05 17:10:00' AND status = 1 AND MOD(id,8)=6 AND deleted = 0表中索引:create index idx_create_time_status o
2021-04-07 16:52:49 474
原创 间隙锁防止幻读
一、前提MVCC只是工作在两种事务级别底下:(a) Read Committed(b) Repeatable Read;因为其他两种:©READ UNCOMMITTED总是读取最新的数据,不符合当前事务版本的数据行,(d)Serializable则会对所有的行加锁。这两种都不需要MVCC;二、间隙锁间隙锁跟MVCC一起工作。实现事务处理:Repeatable Read隔离级别: 采用Next-key Lock(间隙锁) 来解决幻读问题.因此 Mysql Repeatable下面 幻读,可
2021-04-06 22:26:07 269
原创 JDK动态代理原理
一、例子先看一个简单的动态代理例子:car接口public interface Car { public String doSomething();}car实现类public class CarImpl implements Car { @Override public String doSomething() { System.out.println("run ... "); return "car"; }}publi
2021-04-06 22:23:44 96
原创 @Transactional的10种失效情况
1.错误的访问权限@Servicepublic class UserService { @Autowired private UserMapper userMapper; @Transactional private void add(UserModel userModel) { userMapper.insertUser(userModel); }}因为@Transactional生效要走AOP代理,而切面是切不到私有方法的
2021-04-06 22:11:00 376
原创 cpu暴增排查
写了一段测试程序,然后开始执行: @RequestMapping("/for") public String for1() { List list = new ArrayList(); while (true){ list.add(new Byte[1]); log.info("list:{}",list.size()); } }首先使用top命令查看:可见PID为1554的java进程
2021-04-02 16:34:29 197
原创 亿量数据导出优化
一、背景背景在上期已讲,点击这里现在要对着5亿数据做导出,单次导出不超过100万,导出时间不超过10分钟。二、架构设计1、导出功能交互由同步改为异步+通知2、借助es做二级索引,es只存查询条件并返回数据库ID3、用es返回的数据库ID去数据库做全量查询4、使用oss做断点续传5、查询es只返回id 避免回表6、数据库批量查询5000改为1000(经验值范围)7、ES查询由form+size改为scroll再改为searchAfter(解决深分页问题)8、增加机器提高并行处理能力9
2021-04-02 13:11:51 743
原创 亿量数据查询优化
一、背景目前数据库中单表数据量已达到5亿,使用的是阿里云数据库polarDB(mysql plus版);带索引键的查询是没问题的,如果非索引查询或区分度不高的索引查询很慢,聚合查询也非常慢,这种OLTP类型的数据库本来就不适合聚合查询。恰好业务场景就是:分页查询每页需要返回当前搜索条件下的总价钱count(price)每页需要返回当前搜索条件下的总数据量count(*)而搜索条件会强制带上索引键,即使带上索引键,聚合查询还是非常慢,大约要30s左右,基于这个场景下如何优化呢?二、优化步骤
2021-04-02 12:56:22 1266 1
原创 亿量级数据平滑迁移
一、背景随着业务发展,对数据库的要求及数据库的维护成本越来越高,使用云数据库已成为大势所趋;云数据库具有以下优点:1、轻松部署、一键扩容2、实时备份3、高可靠、故障自动切换4、完善的监控目前需要将自建机房中的数据库迁移到阿里云数据库,需要平滑迁移,对上层业务无感,并且发版期间一直有增量的数据写入,而且程序发版期间还有产生双写:方案1:方案2:方案3:方案4:方案5:方案6:方案6执行步骤:1、阿里云数据库增加id自增起始值2、建立M5到阿里云DTS3、建立反项
2021-04-02 11:27:21 192
原创 系统重构、优化实战
背景: 楼主目前正在负责XX公司的退款系统;此系统经过N多人迭代,N多个兼容版本、N多种代码风格,目前已经无法维护下去了;借此机会,将整个系统推倒重来、彻底重构了一遍; 经压测,重构后性能(吞吐量)提升了12倍之前系统架构图:大体介绍下这个系统是干什么的,都做了些什么事:这是一个退款系统,由上游系统发起退款申请(相当于底层服务)多场景:退款的场景有N多种,现在每一种退款都维护一套单独逻辑(需要抽象)退款单组装:接收到退款请求后,做了一些基本的校验,校验通过后去组装退款单实体,组装实
2021-04-02 11:11:20 535
原创 mysql mvcc底层详解+图解
前提:mvcc是mysql底层为提高并发衍生的一种多版本并发控制机制,全称 Multi-Version Concurrent Control,因避免了了加锁操作,因此开销更更低;注意:1、只有在读已提交和重复读两个隔离级别下 mvcc才生效;2、读未提交每次读取都是最新的(快照读),SERIALIZABLE则会对所有读取的⾏都加锁。图解mvcc例如有一张表account,只有id和name属性;如下:idname1a0现要对其做如下变更:(3、4行是为了生成
2021-04-01 23:14:34 517
原创 explain详解
1、id表示查询中执⾏select⼦句或者操作表的顺序:id相同,执行顺序由上至下explain select * from finance t1 join tb_user t2 ont1.create_id=t2.id;如图所示,先查询了t2表,后查询的t1表id不同,如果是⼦查询,id的序号会递增,id值越⼤优先级越⾼,越先被执⾏explain select * from finance t1 where t1.create_id not in(select id from
2021-03-31 12:44:44 241
原创 mybatis原理解析
前提:最近在学习mybatis源码,结合画图跟大家分享下,如有理解有误,欢迎指教。@Test public void test() throws IOException { // 1、获取sqlSessionFactory SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession SqlSession sqlSe
2021-03-26 18:20:27 283 1
原创 线上内存泄露排查
背景:上周网关上线后,隔了几小时突然服务不可用,重启后恢复,隔几小时后依然如此;由于此次网关改动的代码较多,一时不好定位。问题回放:从系统监控图上看,内存一直在增长,最终到爆;抓取到服务器宕机时刻的日志如下:o.netty.util.internal.OutOfDirectMemoryError: failed to allocate看到以上的日志,大体可以知道是直接内存分配不足导致,与系统监控图上看比较吻合;从系统监控图可以看出,自从服务上线后已用内存就一直在申请、上升,没有释放,那
2021-03-26 15:31:11 865
原创 使用eclipse分析线上堆内存溢出
背景:昨晚上完线之后,服务不定时出现响应慢,过一会直接不可用;重启之后恢复正常;过一会问题依旧如此;问题回放初步怀疑是fullgc导致,于是下载gc.log文件通过https://gceasy.io/进行在线分析,经分析确实出现了fullgc问题;如下图:联系运维导出导出dump文件(jmap),并使用了服务器上的eclipse进行dump文件分析:具体分析步骤如下:1、首先eclipse要安装memory analyzer插件;点击eclipse help–>markerplace在
2021-03-25 20:55:38 303
原创 记一次rocketmq事务消息使用不当造成线上事故
场景:最近rocketmq事务消息使用不当导致了线上问题;现象为本地事务执行失败,但是半消息还被发送出去了,最终导致了数据不一致;rocketmq事务消息执行步骤:
2021-03-25 19:49:56 896
原创 spring-BeanPostProcessor与BeanFactoryPostProcessor区别
1、BeanFactoryPostProcessor触发时机不一样,BeanFactoryPostProcessor是在BeanFactory标准初始化之后调用,来定制和修改BeanFactory的内容;所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建;我们可以通过实现BeanFactoryPostProcessor接口向容器中添加BeanPostProcessor、修改bean的定义信息等操作;或者实现BeanDefinitionRegistryPostProcess
2021-03-03 18:26:08 307
原创 spring-容器初始化-refresh()方法(下)
####11、finishBeanFactoryInitialization(beanFactory)
2021-03-03 18:21:35 141
原创 spring-aop原理
一、先从一个简单的aop例子说起1、定义一个切面,切入点为MathCalculator类里的所有方法@Aspectpublic class LogAspects { //抽取公共的切入点表达式 @Pointcut("execution(public int com.aop.MathCalculator.*(..))") public void pointCut(){}; //@Before在目标方法之前切入 @Before("pointCut()") public void log
2021-01-22 14:57:33 233
原创 spring-@Autowired、@Qualifier、@Primary、@Resource使用
1、@Autowired自动注入:、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean(“bookDao”)@Qualifier(“bookDao”):使用@Qualifier指定需要装配的组件的id,而不是使用属性名自动装配默认一定要将属性赋值好,没有就会报错;可以使用@Autowired(r
2021-01-20 14:57:41 602
原创 spring-@value属性赋值
1、@value给属性赋值,使用方式有三种:基本数值SpEL; #{}写${};取出配置文件【properties】中的值(在运行环境变量里面的值)使用如下: @Value("张三") private String name; @Value("#{20-2}") private Integer age; @Value("${person.nickName}") private String nickName;其中第三种需要增加外部配置文件,需要使用@PropertySource
2021-01-20 10:55:02 562
原创 spring-@Conditional条件注解
1、@Conditional条件注解;满足当前条件,这个类中配置的所有bean注册才能生效;使用如下:@Conditional({MyCondition.class})public class TestCondition {}//只有dev环境时 才会加载public class MyCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedT
2021-01-19 19:07:50 211
原创 spring-scope作用域
1、@Scope调整作用域,默认为单实例:prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿request:同一次请求创建一个实例session:同一个session创建一个实例使用如下: @Scope("prototype") @Bean("person") public P
2021-01-19 18:52:45 138
原创 spring-bean注册
1、@Controller、@Service、@Repository、@Component向容器中注册自己写的类;原理是每个注解都对应一个BeanPostProcessor,在容器启动时会扫描这些BeanPostProcessor,将这些注解标柱的类注册到容器中,后续会说到。2、@Bean注册第三方包里面的组件到容器中;类型为返回值的类型,id默认是用方法名作为id,使用如下: //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id @Bean("person")
2021-01-19 18:08:10 118
原创 spring-包扫描的三种方式
1、@Configuration会告诉spring这是一个配置类,与springmvc中的bean.xml是一个效果;使用如下:@Configurationpublic class MainConfig {}2、@ComponentScan告诉spring要扫描的类路径,与springmvc中的<context:component-scan>一个效果;lazyInit制定是否需要懒加载,默认false,懒加载表示程序第一次访问时才加载,否则在容器初始化时加载,excludeFilt
2021-01-19 17:49:14 771
原创 分布式限流redission RRateLimiter使用及原理
前提:最近公司在做有需求在做分布式限流,调研的限流框架大概有1、spring cloud gateway集成redis限流,但属于网关层限流2、阿里Sentinel,功能强大、带监控平台3、srping cloud hystrix,属于接口层限流,提供线程池与信号量两种方式4、其他:redission、手撸代码实际需求情况属于业务端限流,redission更加方便,使用更加灵活,下面介绍下redission分布式限流如何使用及原理:一、使用使用很简单、如下//.
2021-01-18 14:41:49 16473 7
原创 全链路日志追踪traceId(http、dubbo、mq)
一、概述1、目的目前许多系统项目之间的调用,有基于微服务的,有通过HTTP请求的,还有通过mq的。那么在处理一次请求的时候,可能会调用多个服务或者调用多个其他系统功能,这样就会产生很多的日志,此时,如果想查看这一次调用的完整的请求链路的日志时,就会变得比较困难,虽然我们有一些集中的日志收集工具比如ELK,我们需要把这一些日志串联起来,这个问题很关键,因为如果没有串联起来,排查日志就是一件很困难的事情。2、解决办法一般来说,系统之间的调用不外乎两种:http和dubbo。当然还有通过中间.
2020-12-03 17:35:22 11001 8
原创 分布式雪花算法(防重复)
一、介绍简单介绍下雪花算法:核心思想就是使用一个64位bit的long型数字作为全局id;那么这个64位的bit由如下几部分组成第一部分:1bit;0,表示为正数第二部分:41bit,时间戳第三部分:10bit(如果是多机房可以拆分成两部分,即机房部分+机器部分),机器的唯一标识第四部分:12bit,表示的序号,就是某个机房某台机器上这一毫秒内同时生成的 id 的序号由以上的组成部分 我们可以直观看出 集群模式下只要保证第三部分唯一,就可以保证集群模式下不会出现重复的id;.
2020-11-26 10:37:39 5155 2
原创 基于redis分布式锁注解版
思路使用AOP,直接上代码:注解类:@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Inherited@Documentedpublic @interface RedisLock { int expireTime() default 60; String key(); String prefix() default ""; TimeUnit timeUnit() de.
2020-11-26 10:20:13 299 2
原创 责任链模式结合项目实际应用(java、spring)
一、背景楼主所在的公司最近在做重构,楼主负责退款模块的重构工作。退款的方式有很多种,比如微信退款、支付宝退款等等;那么每种退款的前期校验规则有相同也有不同的,如图所示微信和支付宝拥有共同的校验项B,各自拥有自己的校验项A、D,如果有很多种退款方式,那么如何设计一套支持相同校验项服用、不同校验项只在当下场景校验呢?(便于理解 把校验项理解为签名校验、幂等校验等)退款方式 校验规则 微信 A校验、B校验 支付宝 B校验、D校验 二、责任链模式将每个校验项单独封装成一个校
2020-11-24 22:31:36 344
原创 MQ如何保证消息不丢失
一、Rabbit MQ 基础知识1.生产者(Producer): 投递消息的一方生产者创建消息,然后对消息体进行序列化+消息的标签发送给RabbitMQ。2.消费者(Consumer): 接收消息的一方消费者连接到RabbitMQ 服务器,并订阅队列中消息。消费者接收到消息后,先进行反序列化,然后消费进行处理。3.Broker: 消息中间件的服务节点对于RabbitMQ来说,一个RabbitMQ broker可以简单看作一个RabbitMQ服务节点或服务实例。4.队列(Queue
2020-09-03 18:01:33 2126
原创 MQ顺序消费解决方案
一、MQ的顺序问题1.顺序错乱的常见原因 :消息发送:多线程并行发送,有顺序的消息被写入到不同的分区,异常重试。消息消费:多消费者并行消费,或消费者内部启用多线程消费。异常重试。2.为什么要保证消息的顺序 :如果业务上通过消息发送的数据是有前后顺序关系时,则必须保证消息的顺序。例如:通过MQ同步数据时,如果增、改、删的顺序在同步时变为删、改、增,数据将不被删除。二、常见解决方案三、解决方案1、RocketMQ的顺序消息1.Rocket...
2020-09-03 16:18:03 7987
原创 MQ事物解决方案
一、前提:MQ的事务问题有两个层面:1.MQ中间件本身的事务:大多数的MQ中间件都是支持事务的,但这个事务指的是MQ资源本身的事务。例如:通过MQ发送多条消息时,由MQ中间件保证多条消息同时发送成功,或同时发送失败。2.业务事务与MQ事务的一致性:由于业务操作的数据库事务和消息中间件的事务分属于不同的资源,分产生分布式事务问题。除个别MQ中间件外,大部分MQ中间件都不支持分布式事务,无法保证业务事务与MQ事务的一致性。二、产生场景1.消息事务嵌入到业务...
2020-09-03 15:21:38 586
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人