linux

linux之内存

问题 RAM为什么不能持久化? 内存管理的最小单位是什么? pagecache是什么? pagecache与buffercache的区别? 线程的内存大小? tmpfs是做什么的? 内存对齐的作用? 内存 概述 内存是计算机的主存储器。内存为进程开辟出进程空间,让进程在其中保存数据。 内存的大小 内存有一个最小的存储单位,大多数都是一个字节。内存用内存地址(memory address)来为每个字节的数据顺序编号。因此,内存地址说明了数据在内存中的位置。内存地址从0开始,每次增加1。这种线性增加的存储器地址称为线性地址(linear address)。为了方便,我们用十六进制数来表示内存地址,比如0x00000003、0x1A010CB0。这里的“0x”

  • 刘凯
31 min read
other

数据结构堆介绍及应用

什么是堆? 堆是一种特殊的树,只要满足以下两个条件,就可以称这棵树为堆 堆是一颗完全二叉树(完全二叉树要求,除了最后一层,其他节点个数都是满的,最后一层的节点都靠左排列) 堆中的每一个节点都必须大于等于(或者小于等于)其子树中每个节点的值。 每个节点的值都大于等于其子树每个节点的值的堆,我们称之为大顶堆,每个节点的值都小于等于其子树每个节点的值的堆,我们称之为小顶堆。如下图: 从上图可以看出,对于同一组数据,我们可以构建多种不同形态的堆。 如何存储堆? 堆是一颗完全二叉树,比较适合用数组存放,因为用数组存放不需要存储左右子节点的指针,非常节省空间,通过下标就可以找到一个节点的左右子节点和父节点。下图就是一个数组存放堆的例子: 从图中可以看出,下标i的节点的左子节点的下标是i2,右子节点的下标为i2+1,父节点的下标为i/2,

  • 凯文
10 min read
极客

疑难杂症之apollo value的使用

Aoollo config可以通过spring 注解@value注入,但是在使用中发现,如果在不同namespace下配置重复key的config,在注入value时会有问题,注入的value可能不是自己想要的配置 原因是apollo sdk在向spring 配置中添加该配置时,只是用到了key,而未使用namepsace,故当存在不同的namespace下相同key时,无法区分想要哪个配置,且只会保留一个,故会出现在业务使用配置中,通过@Value获取错误的情况,如果使用apollo的注解,指定namespace即不会存在该问题

  • 凯文
1 min read

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个请求 解决方案 暂时解决方案

  • 凯文
2 min read
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

  • 凯文
1 min read
java

20220720-记录一次生产导出问题

问题 线上导出订单时,节点未重启,但是调接口不通,原因是调用三方接口超时错误,查看gc、cpu&内存监控,发现 cpu idle 40% mem.used 3730m,容器是4g 堆大小为3g gc time 大幅增加 故问题原因是由于频繁gc导致 stw,故无法在timeout时间内处理请求 导出订单数量3w+ 临时方案 修改网关接口路由配置,导出接口路由至单独的小流量集群 模拟环境 由于sim环境数据较少,故通过模拟的方式导出,即调整代码逻辑,一直导出第一页订单,

  • 凯文
10 min read
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"):一个代表任意字符串,

  • 凯文
2 min read
java

sentinel介绍及原理

sentinel作用 Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 sentinel整体设计的很精巧,只需要一个sentinel-core便可以运行,它提供了诸如服务降级、黑白名单校验、QPS、线程数、系统负载、CPU负载、流控等功能,可谓是功能非常的强大。 sentinel使用 SphU.entry 手动执行限流逻辑 sentinel使用SphU或者SphO标示一个被保护的资源,比如: Entry entry = SphU.entry("HelloWorld", EntryType.

  • 凯文
11 min read

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

  • 凯文
1 min read

JVM之JIT

JIT概述 即时编译是一项用来提升应用程序运行效率的技术。通常而言,代码会先被 Java 虚拟机解释执行,之后反复执行的热点代码则会被即时编译成为机器码,直接运行在底层硬件之上。 从 Java 8 开始,Java 虚拟机默认采用分层编译的方式。它将执行分为五个层次,分为为 0 层解释执行,1 层执行没有 profiling 的 C1 代码,2 层执行部分 profiling 的 C1 代码,3 层执行全部 profiling

  • 凯文
7 min read

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新增非核心线程 如果新增线程失败,

  • 凯文
3 min read