java 记录一次由jmap导致的gc 问题 服务gc频繁,故需要通过jmap查看jvm内存使用情况,写了一个定时1s执行jmap的工具,结果gc更加频繁,gc原因是Heap Inspection Initiated GC,该问题是由jmap -histo:live导致的 解决方案 由于在执行时添加了live参数,所以在执行该命令前均会执行一次full gc ;故应避免使用jmap -histo:live因为会频繁的full gc,故在执行jmap时,去掉live
other 数据结构堆介绍及应用 什么是堆? 堆是一种特殊的树,只要满足以下两个条件,就可以称这棵树为堆 堆是一颗完全二叉树(完全二叉树要求,除了最后一层,其他节点个数都是满的,最后一层的节点都靠左排列) 堆中的每一个节点都必须大于等于(或者小于等于)其子树中每个节点的值。 每个节点的值都大于等于其子树每个节点的值的堆,我们称之为大顶堆,每个节点的值都小于等于其子树每个节点的值的堆,我们称之为小顶堆。如下图: 从上图可以看出,对于同一组数据,我们可以构建多种不同形态的堆。 如何存储堆? 堆是一颗完全二叉树,比较适合用数组存放,因为用数组存放不需要存储左右子节点的指针,非常节省空间,通过下标就可以找到一个节点的左右子节点和父节点。下图就是一个数组存放堆的例子: 从图中可以看出,下标i的节点的左子节点的下标是i2,右子节点的下标为i2+1,父节点的下标为i/2,
docker docker 容器指定内存 创建容器 docker run -m 4g --memory-swap -1 已存在容器 docker stop fe0eb27f487b docker update fe0eb27f487b -m 128m --memory-swap -1 docker start fe0eb27f487b
kafka kafka队列小贴士 kafka如何实现延时消息 rabbitmq可以通过死信队列实现延时消费 import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.kafka.clients.consumer.*; import org.apache.kafka.clients.producer.KafkaProducer;
mysql mysql 获取全部表名 获取库db1的全部表名 select table_name from information_schema.TABLES where TABLE_SCHEMA='db1' and TABLE_TYPE = 'base table'; 获取path_names_png字段,截去最后一个‘-’及以后的部分 SELECT path_names_png, LEFT(path_names_png, char_length(
mysql 记录一次签到表分表的过程 建表 create table sign_{0,9}{ xxx } 定制策略 创建ModShardingStrategy 实现 AbstractShardingStrategy 修改mapper mapper 添加注解 @TableSharding(tableName = "activity_xxx", shardBy = "uid",strategy = "com.xxx.ModShardingStrategy") 添加拦截器 @Bean("
极客 疑难杂症之apollo value的使用 Aoollo config可以通过spring 注解@value注入,但是在使用中发现,如果在不同namespace下配置重复key的config,在注入value时会有问题,注入的value可能不是自己想要的配置 原因是apollo sdk在向spring 配置中添加该配置时,只是用到了key,而未使用namepsace,故当存在不同的namespace下相同key时,无法区分想要哪个配置,且只会保留一个,故会出现在业务使用配置中,通过@Value获取错误的情况,如果使用apollo的注解,指定namespace即不会存在该问题
linux curl 展示http status 正常使用curl访问 http 时,如果出现http status不为200时,无响应时,看不到http status,即无任何展示,如果需要查看http status 可通过下面的命令 curl -w '%{http_code}' https://baidu.com
20220707-记录两个线上问题 线上限流问题 问题 定向发券时,部分用户发券失败,原因是service-1调用service-2时被ingateway限流(http 596 status),service-1执行fallback逻辑,抛出异常;活动发券用户1602+394+224*1左右,故批量时qps在 700左右,但是限流配置的是1k,故不应被限制 原因 inrouter的限流是单节点限流,比如配置限流策略是1000,存在17个inrouter节点,即每个节点的限流qps为58,当该节点qps超过58时,即会被限流响应598,上述问题时总qps为722,故单节点平均为 42,当某一节点倾斜量超过16时,超过的请求即会被限流,共限流29个请求 解决方案 暂时解决方案
golang go随机数 我们在通过go获取随机数时,会发现每次获取的均一致,如下面的程序,无论执行多少次,打印的结果均是81、87、47、59 for i := 0; i < 40; i++ { println(rand.Intn(100)) } 81 87 47 59 这是因为在默认情况下,go的rand会使用相同的源来产生一个确定的伪随机数序列,即产生一个不变的数列。 由于源代码已经发布到 Go 的官方标准库中,因此任何运行此程序的计算机都会得到相同的结果。 但是,由于 Go
java 20220720-记录一次生产导出问题 问题 线上导出订单时,节点未重启,但是调接口不通,原因是调用三方接口超时错误,查看gc、cpu&内存监控,发现 cpu idle 40% mem.used 3730m,容器是4g 堆大小为3g gc time 大幅增加 故问题原因是由于频繁gc导致 stw,故无法在timeout时间内处理请求 导出订单数量3w+ 临时方案 修改网关接口路由配置,导出接口路由至单独的小流量集群 模拟环境 由于sim环境数据较少,故通过模拟的方式导出,即调整代码逻辑,一直导出第一页订单,
http http之Range 介绍 http进行文件访问时,可通过header Range指定请求的位置,实现分段下载,断点续传的功能 使用 正常访问文件 curl --location --request GET 'https://pics3.baidu.com/feed/574e9258d109b3deaee28959b7a2cd8b800a4c4d.png?token=686e4f2c779c94c6c4af388ff06104d2' 访问部分字节 curl --location --request GET 'https://pics3.baidu.com/feed/574e9258d109b3deaee28959b7a2cd8b800a4c4d.png?
other 分布式id之雪花算法 为什么使用雪花算法 数据库自增id,在分表的情况下会导致重复 uuid不是自增的,对于 innodb会导致页分裂和碎片的问题 雪花算法是按时间戳递增的,分布式id生成算法 使用 雪花算法的实现非常多,各大厂都有自己的实现,本文以mybatisplus为例 添加依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-core</artifactId> <version&
git git clone时出现 info/refs not valid错误 git clone/pull时报错 info/refs not valid: is this a git repository 执行git命令时,添加用户及密码 用户名:kevin 密码:k@12345 仓库地址:http://1xx.1xx.1.1xx:80/kevin/project.git 命令格式 (注:@转成%40)
mysql mysql通过MapperScan实现多数据源 MapperScan org.mybatis.spring.annotation.MapperScan 在SpringBoot中集成MyBatis,可以在mapper接口上添加@Mapper注解,将mapper注入到Spring,但是如果每一给mapper都添加@mapper注解会很麻烦,这时可以使用@MapperScan注解来扫描包。 @MapperScan注解只会扫描包中的接口,不会扫描类,所以可以在包中写Provider类。 属性 basePackages @MapperScan("com.demo.mapper"):扫描指定包中的接口 @MapperScan("com.demo..mapper"):一个代表任意字符串,
java sentinel介绍及原理 sentinel作用 Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 sentinel整体设计的很精巧,只需要一个sentinel-core便可以运行,它提供了诸如服务降级、黑白名单校验、QPS、线程数、系统负载、CPU负载、流控等功能,可谓是功能非常的强大。 sentinel使用 SphU.entry 手动执行限流逻辑 sentinel使用SphU或者SphO标示一个被保护的资源,比如: Entry entry = SphU.entry("HelloWorld", EntryType.
jvm之Spi 作用 SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。 使用 开发接口模块 public interface PayService { String pay(); } 开发实现模块 public class AliPayService implements PayService { @Override public String pay() { return "ali"; } } 添加service 在resouces下创建目录META-INF/services 在services添加文件com.xxx.PayService,
Reactor网络模型 主-从Reactor网络模型 Main reactor thread 负责绑定监听端口 绑定端口后通过单线程acceptor建立tcp连接 建立tcp连接后通过epoll注策读事件 sub-reactor dispatch 一个四核 CPU服务器,我们可以设置 sub-reactor 为 4 负责监听tcp连接读写事件 当acceptor建立连接后,交由sub-reactor中的一个处理 收到tcp读事件后,交给工作线程处理任务 与单reactor线程相比(即读写事件监听线程和acceptor线程为同一线程),单reactor 线程既分发连接建立,又分发已建立连接的 I/O,有点忙不过来,在实战中的表现可能就是客户端连接成功率偏低。 threadpool 任务任务线程池 由于处理任务比较耗时,故将任务处理线程与tcp
linux之seletor/poll/epoll 什么是 I/O 多路复用 把标准输入、套接字等都看做 I/O 的一路,多路复用的意思,就是在任何一路 I/O 有“事件”发生的情况下,通知应用程序去处理相应的 I/O 事件。这样就可以同时监听多个 I/O 事件。 select 介绍 int select(int maxfd, fd_set *readset,
redis telnet连接redis 连接 telnet 10.85.172.48 30901 get get limit:652824:639247269906973726:1166102 set set limit:652824:639247269906973726:1166102 '["java.util.ArrayList",[{"@class":"com.wujie.limit.domain.
JVM之JIT JIT概述 即时编译是一项用来提升应用程序运行效率的技术。通常而言,代码会先被 Java 虚拟机解释执行,之后反复执行的热点代码则会被即时编译成为机器码,直接运行在底层硬件之上。 从 Java 8 开始,Java 虚拟机默认采用分层编译的方式。它将执行分为五个层次,分为为 0 层解释执行,1 层执行没有 profiling 的 C1 代码,2 层执行部分 profiling 的 C1 代码,3 层执行全部 profiling
java之优先级队列 PriorityQueue 案例 package com.kevin.container; import java.util.PriorityQueue; import java.util.Random; public class PriorityQueueCase { public static void main(String[] args) { PriorityQueue priorityQueue = new PriorityQueue(); int count = 10; for (int i
jvm之线程池 java线程池实现继承关系 Executor==>ExecutorService-->AbstractExecutorService==>ThreadPoolExecutor Executor-接口 execute,执行某个Runnable实现类 ExecutorService-接口,较Executor提供了更多的功能 submit,执行Callable实现类,返回值通过Future返回 AbstractExecutorService-线程池抽象类 实现了submit方法 在执行submit方法前会将Callable转为FutureTask类,然后调用execute方法执行 FutureTask是Runnable的实现类 线程池基本都继承该抽象类 线程池实现类 ThreadPoolExecutor 实现了execute方法,在该方法中判断核心线程数 如果小于核心线程数,则通过addWorker新增核心线程执行该command 如果小于核心线程数,则将command添加至任务队列中 如果添加队列失败,则继续通过addWorker新增非核心线程 如果新增线程失败,
java线程池之ForkJoinPool 作用 计算机中一个任务一般是由一个线程来处理的,如果此时出现了一个非常耗时的大任务,比如对一个大的ArrayList每个元素进行+1操作,如果是普通的ThreadPoolExecutor就会出现线程池中只有一个线程正在处理这个大任务而其他线程却空闲着,这会导致CPU负载不均衡,空闲的处理器无法帮助工作。ForkJoinPool就是用来解决这种问题的,将一个大任务拆分成多个小任务后,使用fork可以将小任务分发给其他线程同时处理,使用join可以将多个线程处理的结果进行汇总;这实际上就是分治思想的并行版本 Java8中的parallelStream API就是基于ForkJoinPool实现的 ForkJoinPool的线程使用的是 Thread子类ForkJoinWorkerThread 实例 我们在提交任务时,一般不会直接继承ForkJoinTask,只要继承它的子类即可,框架提供了两种子类: RecursiveAction:用于没有返回结果的任务(类似Runnable) RecursiveTask:用于有返回结果的任务(类似Callable) public class ForJoinPollExecutor { public static