自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

u010900754的专栏

真心希望国内博客环境 多一些原创 少一些复制

  • 博客(635)
  • 资源 (3)
  • 收藏
  • 关注

原创 【SpringMVC】目录

【SpringMVC(一)】父子容器 web应用 容器启动 原理【SpringMVC(二)】HandlerMapping【SpringMVC(三)】HandlerAdapter【SpringMVC(四)】三种 HandlerMapping【SpringMVC(五)】三种 控制器【SpringMVC(六)】ArgumentResolver 使用 及 原理【SpringMVC(...

2019-08-11 19:39:52 415 1

原创 【后续不再更新】转战 github了

GitHub - miracle2138/tech-blog

2022-01-17 19:45:23 1140

原创 【数据结构与算法】跳表

跳表一种针对链表的快速查询数据结构。理论分析,给定一个静态的链表,如果每两个节点构建一个上层索引链表,查询时间变成On/2。如果再往上构建,变为On/4。一直往上构建到k层,假设k层有x个节点,那么只需要遍历Ox。也就是只有最上层的链表需要遍历,之下的链表最多3个节点是常数级别。又因为最上层的链表数最多为2,所以可以有这个结论:每一层至多遍历3个节点。那么总共几层呢?显然是logn,所以这个跳表的查询时间复杂度是logn。在实际运用的时候,链表会动态添加或者删减,我们需要同步调整索引结构,此时无法完全

2021-06-03 10:41:20 892 1

原创 【Java】ThreadLocal

ThreadLocal作用线程级别变量隔离,减少多线程访问变量时加锁带来的性能损耗。缺点使用不当可能导致oom。原理弱引用是精髓。get方法 public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = m

2021-05-17 00:02:44 926

原创 【Java】四种引用

Java引用类型分为4种。1.强引用正常来说,用一个引用指向new出的对象,都是强引用类型。比如String s = new String(""); 这里的s就是一个强引用。如果对象被强引用指向,那么这个对象无论如何都不会被gc回收,即便发生oom。2.软引用String s = new String("abc");SoftReference<String> r = new SoftReference<>(s);软引用的特点是,如果对象仅仅被软引用指向,gc时

2021-05-16 23:31:11 247

原创 【Kafka(二)】日志及索引文件

每一个分区一个文件夹,一个分区对应多个文件。当满足一定条件后,会生成新的文件。每一个文件叫做一个日志段,每一个日志段会关联两个索引文件,一个是偏移量索引另一个是时间戳索引。日志段以本日志内的第一条消息的偏移量命名。段内的日志偏移量是相对偏移量。一个分区只有最新的日志段是可写的,其余的都是只读。索引文件:并非每一条消息都对应一个索引项,而是积累到一定数量后,插入一条索引项。1.偏移量:按照偏移量排序,存放的是偏移量到物理位置,查找时二分法查找。2.时间偏移量:按照时间戳排序,查找时二.

2021-04-28 23:47:43 623

原创 【Kafka(一)】日志格式

任务数据想要持久化或者进行网络传输,都需要进行序列化。序列化方式可以分两种:字节流或者字符流。字节流:机器友好,传输效率更高,占用更小的空间,如果追求性能,优先考虑。常见的比如mysql、kafka等,都使用的字节流协议;字符流:人类友好,可读性更好,拿到消息体后便可解析消息内容。但是效率较低,毕竟一个字符至少占用一个字节。常见的比如http协议就是字符流协议;下面看下kafka的消息格式或者协议。kafka消息格式经过了几个版本。消息以消息集的形式存在。消息集内的每一条消息由off

2021-04-28 23:08:51 340

原创 【网络IO模型(三)】Reactor 模式

/** * Reactor模式简述 * * Reactor负责轮询selector,将就绪事件分发给handler处理。 * handler大致有两种: * 1.acceptor:负责建连,建连后注册io handler; * 2.io handler:负责处理io读写事件; * * 所以Reactor模式是一种事件响应式模式。提前注册handler。selectionKey的作用是将handler与channel关联(注册事件时不能指定handler) * 当select返回就绪事.

2021-02-27 23:22:34 345

转载 Linux 磁盘IO方式

用户态 vs 内核态:操作系统也是程序,有对应的程序代码,而且也要占用内存。计算机的部分内存以及部分函数就是专门分给操作系统使用的,也就是内核态。而普通的用户进程只能访问用户内存,如果需要使用系统资源,需要发起系统调用,也即转为内核态。内核态是对计算机资源的保护。Linux 磁盘IO方式1.基于中断的IO用户进程发起IO请求,进入内核态。cpu向硬件设备发送IO指令,随后cpu挂起当前进程,调度其他进程执行。当硬件设备处理完成后,发送中断信号给cpu,中断具有最高优先级,cpu会挂起当.

2021-02-27 16:46:55 458

原创 【网络IO模型(二)】Linux IO 模型

作为软件开发者特别是server开发,平时要面对大量的跨进程交互场景,各种跨进程调用。虽然现在的开发语言为我们提供了很好的封装,不用过度关心底层网络io的细节,但是作为开发者,还是要了解基本的原理。我们面对的是一个个黑盒,但是为了排查问题或者写出性能更好的程序,必须当成白盒来研究。Linux IO 模型。看看到掘金上的一篇文章,做一个笔记吧。https://juejin.cn/post/6892687008552976398https://www.jianshu.com/p/486b0965c2

2021-02-27 15:48:10 144

原创 【网络IO模型(一)】BIO vs NIO

先回顾下几个概念。阻塞 vs 非阻塞:指的是调用者线程会不会被阻塞。BIO就是一种阻塞io,如果没有就绪,调用者线程会被阻塞挂起。而NIO是非阻塞的。同步 vs 异步:指的是调用方式,同步调用可以理解为调用结果需要调用者主动获取,而异步调用则是使用回调/通知机制,将结果回调给调用者,调用者无需关心。可以看到,二者是两个维度的概念,没有绑定关系。同步调用可以是阻塞的也可以是非阻塞的,比如BIO和NIO。异步调用通常是非阻塞的,比如AIO。目前现状是BIO和NIO占绝大多数的场景,AIO却用的不

2021-02-27 15:13:23 213 1

原创 多线程一定好吗?

答案是不一定,怎么看这个问题呢?1.从操作系统多核角度来看,多线程可以利用现代操作系统多核并行处理的优势,所以从这个角度来说,多线程会提高性能。2.如果只针对一个cpu看,cpu密集型的程序,多线程肯定没有单线程效率高。因为线程本身是需要消耗资源,包括为各个线程分配的内存以及线程上下文切换时消耗的cpu资源。所以说纯cpu的程序,多线程效率会降低。但是,现实往往不会这么理想,当今世界,很多系统都需要经过网络io,所以并不是cpu密集型。当程序执行需要执行io操作时,cpu就会空闲下来,而io往往会比

2021-02-27 13:20:33 745

转载 【Java】异常日志只打印一行

一直以为是日志系统的功能,今天发现是jvm实现的,参数是:OmitStackTraceInFastThrow,并且只针对特定5种异常开启。详见:https://www.javajike.com/article/1768.html

2021-02-23 11:10:19 1464

原创 【git】极客时间学习笔记

变更的过程:工作区->(1)->暂存区-(2)->commit发生在(1):工作区相对于暂存区的变化。使用git diff,可以查看区别;使用git checkout,可以用暂存区恢复工作区;发生在(2):暂存区相对于commit的变化。使用git diff --cached,可以查看区别;使用git reset HEAD,可以使用HEAD的已提交内容恢复暂存区,暂存区的变更将会返回到工作区;使用git rm = rm + git rm;使用git mv = mv + git a

2020-12-06 00:29:48 192

原创 【git】blob、tree、commit

git存储三种类型:commit、tree与blobblob指的是文件,一个文件的一个版本对应一个blob对象,比如v1的版本的a.txt文件是一个blob,然后对a.txt进行了修改,重新commit为v2版本后,会多一个v2版本的blob,也就是说同一个文件,有几个版本就有几个blob对象这里也引申一下git的存储机制。首先git需要管理版本,那么需要能够恢复到之前的版本,所以可以肯定的是需要存储整个git仓库的每一个版本,有两个思路,一是存diff;二是存全量文件,也就是存快照。git使用的是后

2020-12-05 20:40:21 1984

原创 【Kafka】消费者 位移提交

kafka位移机制broker维护消费者的消费位移信息,老的版本存储在zk上,新版本存储在内部的topic里。本质上,位移信息消费者自己维护也可以,但是如果消费者挂了或者重启,对于某一个分区的消费位移不就丢失了吗?所以,还是需要提交到broker端做持久化的。提交方式分为自动和手动。自动是默认的行为,当然可以通过配置覆盖关掉自动提交。自动提交是consumer以一个时间间隔周期性地提交offset,比如每隔5s提交一次。提交发生的时机是poll调用时,会将上一次消费的位移信息提交到broker。自动提

2020-11-22 21:39:53 788

原创 Netty HashedWheelTimer 介绍

HashedWheelTimer是netty开发包里时间轮组件,可以用于提交延迟任务。Java里的Time组件也具备相同的功能,不过Time是基于优先队列实现的,相当于需要对所有的任务基于执行时间排个序,复杂度是logn。而HashedWheelTimer是另一种思想,预先放置一定数量的任务槽,任务提交时,根据延迟时间放入对应的槽位。工作线程利用sleep模拟tick,将到达的槽位里的任务取出,依次执行。极端情况下是On,如果槽位足够大,接近于O1。使用 public static void

2020-11-22 19:16:53 1288

原创 【Java】Guava里Maps#transformValues方法导致异常无法catch

/** * guava开发包里的Maps#transformValues方法可能会导致异常catch不住。当然不是说guava实现有bug,是指使用者很可能不了解其实现原理,导致问题发生。 * Maps#transformValues的实现是lazy的,也就是调用该方法生成的map不是替换value之后的map,而是原始value+transfer function的map,是一个内部实现类TransformedEntriesMap。 * 也就是说我们的transfe...

2020-11-16 14:00:02 838

转载 【MySQL(二十三)】GTID 复制

本来想自己搭建,结果各种error,放弃。。。(mysql太难用。。。没做过运维)使用传统的基于文件位置的方式:需要slave指定复制的文件和位置,可能不准,位置靠后会少日志,位置靠前可能冲突,但是宁可冲突也不能少,所以需要手动跳过,不太方便。基于GTID的模式,每一条master生成的binlog,会打上一个gtid,gtid的格式是serverid:txid。所以在集群里可以认为每一条事务的gtid是唯一的。slave执行时,会记录自己执行过的gtid集合。如果需要换主,就将自己的gtid集

2020-11-15 23:09:05 267

原创 【Protobuf(五)】Any.park

protobuf中的消息定义需要指定类型,试想一下,如果需要一种通用的类型该怎么办?protobuf中提供了Any机制,可以让我们在protobuf定义中不指定具体类型,在运行时指定类型进行解析,有点类似编程语言里的泛型思想(姑且这么说吧。。。)message TestParams1 { uint32 id = 1; string name = 2;}message TestMsg7 { google.protobuf.Any pass_through = 1;}

2020-11-15 22:14:44 627

原创 【Protobuf(四)】消息格式

protobuff是一种平台语言无关的消息序列化协议,相比于传统的json、xml,序列后的空间更小,但是无法自解释,需要结合额外的proto定义文件才能反序列化,当然这样也更安全。下面记录一下protobuff消息格式。protobuff消息序列化后是多个key-value对,每一个字段对应一个key-value对。key-value遵循如下格式:tag|type (length) datatag|type:tag指的是字段的序号,这个一旦定义就不能更改,否则无法解析。type用于标识key-

2020-11-15 16:08:25 968

原创 【Protobuf(三)】Varints 与 Zigzag 编码

在计算机中,整数值通常有两种类型:32位以及64位,在Java中分别对应的是int和long,在C++中分别对应的是int32/uint32和int64/uint64。整型值按照二进制补码的形式存放。而且是定长的。也就是不论数值大小,类型一旦固定,占用的bit位数就是固定的。那么protobuff协议如何序列化一个整数值?protobuff使用Varints编码格式来编码整数,这个协议最大的特点是变长编码。怎么理解?也就是一个整数值编码后的字节数是不确定的,数值越小,占用的字节数也越少,比如127以

2020-11-14 21:44:27 1105

原创 【MySQL(二十二)】一主一从换主

一主一从架构切主的两种方案可靠性优先:先等seconds_behind_master小于一个阈值;设置Master为只读;等待Slave完全同步了Master的数据;设置Slave可写;切写的流量到Slave;这中间,当设置Master为只读时,整个系统不可写,所以又不可用的时间。这也是为什么一开始就最好等seconds_behind_master很小时在做这个事情,不然主从延迟很大,不可用的窗口期就很久。可用性优先:不等Slave完全同步,直接设置Slave可写,并且切流量。这个

2020-11-04 23:53:34 553 1

转载 记录一些 auth2 微信授权相关的信息

https://juejin.im/post/6844903789044973575

2020-09-20 20:22:33 254

原创 【Linux】问题排查

参考:https://fredal.xin/java-error-check排查cpu问题1.使用top命令查看进程top2.使用top命令查看线程top -H -p pid,这里-H表示详细展示线程信息3.打印线程idprintf '%x\n' pid4.使用jstack命令查看线程栈jstack pid | grep tid -A50有了线程堆栈信息,就可以方便排查耗cpu高的代码段了。另外,还可以查看总的线程状态jstack pid | grep 'ja

2020-09-12 11:17:59 280

原创 【MySQL(二十一)】binlog 事件

binlog时机事务提交时写入binlog,但是binlog持久化到磁盘与sync_binlog参数有关:0:只fwrite写入操作系统cache,由操作系统决定什么时候持久化到磁盘,及fsync;1:fsync直接写入磁盘;n:提交n个事务后fsync;1最安全,0性能最好;binlog文件有两种,一种是binlog的索引文件,也即xxx-bin.index,另一种是binlog文件。索引文件:其实就是存储了当前所有binlog文件的文件名。比如:./mys.

2020-09-07 23:47:33 597

原创 【Protobuf(二)】protobuf3 默认值

/** * 关于protobuff3 默认值问题 * 首先,pb对象的get方法永远不会有null,如果没有设置,会生成对应的默认值 * * 如果属性值是一个message,那么pb会为这个属性生成一个hasXXX方法,可以用这个方法判断是否设置了这个属性 * 对于其他属性,比如string,uint32等等,如果没有设置,get出来的将会是控制,比如string就是"",uint32就是0,此时无法区分是没有设置还是设置了默认值,需要业务自行约定...

2020-09-03 13:30:09 5052 3

原创 【Java】 java -jar 命令 传递系统参数 与 main函数参数 顺序

package com.liyao.runner;/** * 用法: java [-options] class [args...] * (执行类) * 或 java [-options] -jar jarfile [args...] * (执行 jar 文件) * 可以看到,jvm参数和程序参数的传参位置是不同的,jvm参数常见的是一些系统变量,会通过-D参数指定,这类型参数是[-options]里的,需要放在执行的主类名或者jar包之前.

2020-09-03 11:23:07 3834

原创 【设计】基于redis的简单频控实现

场景:xxx时间内只能yyy次在redis里维护一个数字类型的k-v,key的生成策略与频控的维度有关,比如是用户级的频控,那么key就是一个userId;如果是总频控,那么key就是一个string常量。key的过期时间就是频控的时间间隔,在创建key的时候设置过期时间。过频控时,需要将key的计数值自增。关于自增的时机:第一种:先get再incr。第二种:先incr再get。这两种都可以,看具体的场景。如果过了频控,后续的业务操作还有其他条件,不一定成功,这种需要用方案一。比如发

2020-08-22 14:07:37 1094

原创 【设计】计数(二)普通计数

这里说的是非基数类型的计数。对于这类型计数,可以只使用一个变量存储计数值,比如点赞数,直接用一个like_count变量逐步累加就行。但是考虑一个复杂场景,比如记录每一个作品的点赞数,这个时候就需要加一个作品维度了,如果使用mysql记录,那么scheme可能是:photo_id,like_count。再复杂一些,作品里可能有多个计数的维度,比如除了点赞计数,还有评论计数,分享计数等等,那看上去需要每一种计数类型都建一张表了,其实也不用,可以再一列type,表明计数类型:photo_id,typ

2020-08-17 23:41:00 144

原创 【设计】计数(一)基数计数

所谓基数计数就是统计不重复元素的个数,典型的场景比如页面uv数,这类计数的特点是需要去重。第一种思路——精确计数即存储所有所有不重复元素的值,用一个set数据结构存。比如存储访问某一个页面的全部去重用户id,需要拿计数值时,只需要计算这个set的元素数目即可。这个set根据场景,可能是内存中一个set数据结果,可能是mysql数据库中的一个表,也可能是redis里的set等等。这个方案在基数值不大的情况下是可以的,毕竟方案本身足够简单,但是如果基数值很大时,就会有问题,这个set会很大,存储

2020-08-16 16:32:07 556

原创 select poll epoll

select:1024个描述符,需要拷贝描述符;poll:不限制描述符,需要拷贝描述符;epoll:分为了三个函数调用,由create创建一个epoll描述符,由ctl设置描述符列表,只需要设置一次,由wait调用取得各描述符就绪事件。因为对函数进行了拆分,所以只需要在ctl里设置描述符列表即可,解决了每一次都需要拷贝描述符的问题。参考:https://segmentfault.com/a/1190000016400053...

2020-08-16 16:14:16 108

原创 【Java】正则表达式 Pattern Matcher

Pattern:生成一个正则表达式的模板,一般而言,不会用到Pattern的其他方法。步骤:1.首先调用其静态方法compile,生成一个正则表达式的模板;2.调用生成的Pattern实例的matcher方法,获得一个Matcher类型的实例;Matcher:是一个有状态的类型,正则匹配的过程都是在这个类里完成的。为什么是有状态的呢?要进行正则匹配,我们需要调用其匹配的方法,有些匹配方式比如子串匹配,可能有多个结果,需要我们多次调用才能获得结果,可以理解为迭代器的流程,需要一步一步通知M

2020-08-09 23:46:23 2245

原创 【Jackson】@JsonAnyGetter 和 @JsonAnySetter

@JsonAnySetter可以将序列化时未识别到的属性都扔进一个map里。@JsonAnyGetter将map里的属性都平铺输出。model类:public class JsonModel1 { private long id; private String name; private Map<String, Object> map; public long getId() { return id; }

2020-08-09 16:31:31 436

原创 【Jackson】@JsonProperty,@JsonSetter,@JsonGetter,@JsonAlias 注解

@JsonProperty:可以用于属性和getter/setter方法上,用于重命名属性名,包括序列化和反序列化时。另外可以指定一个access属性:READ_ONLY:只在反序列化时有这个属性;WRITE_ONLY:只在序列化时有这个属性;READ_WRITE:序列化和反序列化时都有;@JsonSetter/@JsonGetter:@JsonSetter只能用于setter方法,@JsonGetter只能用户getter方法,只用二者中的一个标签时,与@JsonProperty.

2020-08-09 16:01:31 2956

原创 Supervisor Mac 使用介绍

官网:http://supervisord.org/running.html简介:是一个用python写的进程管理工具。生产环境或者测试环境,如果担心服务以外挂掉,可以考虑使用supervisor管理进程。安装:可以使用pip,但是由于是mac系统,更倾向于用brew:brew install supervisor/usr/local/etc/supervisord.ini也是supervisord的默认配置文件。我们先看下配置文件的最后两句:[include]files =

2020-08-09 15:36:39 731

原创 【MySQL(二十)】mysql8 docker 主从 搭建

没做过DBA的工作,发现整一套mysql环境是真的难。。。本人用的mac,平时单机测试,用brew装了一个本地的mysql,这次想搞搞主从,就想着用二进制包在特定目录下搭建一下,发现各种坑。。。根本搭不起来。mysql不同版本的命令都不一样,而且有很多设定其实比较坑,比如有些参数必须是第一位,指定配置文件是--defaults-file而不是--default-file,这些命令你不研究研究官网,根本没法使,但是也没时间。。。没办法,后面决定用docker整了,这里记录下。参考:https://s.

2020-08-02 23:25:32 219

原创 【Java】同步/异步 vs 阻塞/非阻塞

今天看到一个回答,太精确了:https://www.zhihu.com/question/19732473第二条回答个人理解:这两个维度是两个完全不同的维度,处于不同层级。阻塞/非阻塞,侧重于api的实现形式,调用者调用后,是否是阻塞的。同步/异步,应该是更高一级的概念,是说调用结果的获取,是否需要调用者自己去主动获取。同步调用,调用者需要主动获取,可能是阻塞的也可能是非阻塞的。而异步则不需要,比如调用时提供回调函数,有结果了调用回调通知。...

2020-08-01 14:41:31 183

原创 【Java】okHttp3 简单使用

之前用的RestTemplate,发现一个multipart的http请求始终发不成功,后面就试了下okHttp,发现真的好用,api太清爽了,记录一下使用:package com.liyao;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import org.jetbrains.annotations.NotNull;import org.junit.Test;

2020-08-01 14:19:20 2354

原创 【MySQL(十九)】复制 过程

主库将数据写入本地binlog文件中;从库连接,指定起始位置;主库的binlog dump线程开始将binlog内容发送给从库;从库的io线程将收到的binlog内容写入到本地的relay log中;从库的sql线程将relay log应用到数据库中;...

2020-07-05 19:23:33 148

设计模式的 课件

主要讲解了 设计模式的相关内容 包括类图等其他

2014-04-15

head first 审计模式

headfirst 一系列书籍中 对设计模式的讲解 很容易理解

2014-04-15

shell编程 详解

主要 讲解了linux中shell编程的相关内容 基础的语法 等

2014-04-15

空空如也

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

TA关注的人

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