- 博客(301)
- 收藏
- 关注
原创 C++知识点
C++ 容器&算法 API (分类的很好)https://github.com/huihut/interview/tree/master/STLC++语法相关https://github.com/huihut/interview#ccleetcode. C++ 题解(看着是leetcode 148)file:///Users/hanyunchang/Downloads/leetcode-cpp.pdfC++面经(参考) (hard的题目没有必要所有题目都会,挑自己感兴趣的)评论区自问
2022-02-09 08:57:39 422
原创 常见数据结构
堆:通常用数组构建,核心操作,上浮(最简单)、下沉、构建堆、二叉搜索平衡树(AVL):任意节点的两棵子树的高度差的绝对值小于2核心操作,旋转 2种单旋+4种双旋的情况B树:B树定义及关键点的推导定义:一棵多路平衡的查找树,所有叶节点在同一层,一棵m阶的B树,每个非叶子节点最多有m个子节点,所有非根父节点至少有m/2向下去整个儿子节点。红黑树:4条规则及其证明图相关并查集:最短路径Dijkstra(迪彻斯特拉)算法:算法图解单源最短路径,贪心算法,可用反证法证明。最短路径Floy
2021-02-28 18:50:29 179
原创 内存/CPU占用过高如何解决
内存占用过高时free 看内存余量ps 看占内存高的进程top 看最高进程的最高线程jmap 将该线程导出堆转储文件利用visualVM分析该文件CPU占用过高时top查看cpu占用较高的进程top查看cpu占用最高进程的最高线程idjstack导出该进程堆栈使用情况的stack文件cat+grep+线程id浏览相关日志...
2021-02-20 15:46:55 553
原创 数据同步任务:binlog方案与消息队列方案对比
binlog方案原理优点方案简洁,mysql端发生数据变更后只需要将对应日志发送给接收端,不必考虑数据一致性问题。缺点是否能够过滤掉不必同步的数据有待考察只支持监听消息变更,不支持将原有数据进行同步消息队列方案优点可以支持全量同步与增量同步,在原系统不涉及分布式事务的情况下,实现较为简单。另外该方案原生就可以自主选择监听哪些表的变更。缺点需要考虑数据一致性问题(可将dml语句与消息的发送放在一个事务中解决,但是如果系统支持分布式事务则更加复杂);使用到消息队列需要考虑消息的重复(消
2021-02-20 14:26:09 850
原创 数据同步的设计
线程模型,全量数据同步的线程池+增量数据同步的线程池+单个消费者线程进行拉取数据。线程池参数第一个线程池,管理全量同步任务的core size: 10max size:100存活时间:10ms阻塞队列:LinkedBlockingQueue,容量为50拒绝策略:拒绝策略为抛出异常线程工厂:实现了ThreadFactory接口,为线程个性化命名,方便排除bug第二个线程池,管理数据消费线程的core size: 0max size:50存活时间:0阻塞队列:LinkedBlocki
2020-12-30 14:24:12 431
原创 数据引擎/聚集索引
存储引擎对比MYISAM索引与数据分开存储,所有索引级别相同,对应的都是指向真正数据的指针,适合读多写少的场景。不支持事务,锁的最小粒度为表锁,不太适合高并发读写。不支持崩溃后的安全恢复。INNODB一个聚集索引外加多个非聚集索引。支持事务,锁的粒度最小为行锁。支持外键。支持崩溃后的安全恢复。MEMORY该存储引擎将数据存储在内存中,适合追求更快的响应速度,适合数据规模小并且不担心数据丢失的场景。聚集索引与非聚集索引聚集索引是指B+树的叶节点存储了整行的数据,非聚集索引是指B+树的叶
2020-12-14 00:21:21 175
原创 消息队列发布订阅模型设计及其原因
模型最开始是这样的:后来为了可以处理消费者消费能力与生产者生产能力不匹配的问题。问题1:生产者生产能力低于消费者消费能力。 最简单的想法增大生产者生产能力或者减小消费者消费能力。前者不可取,因为消息能生产出来的多少取决于系 统,取决于业务。而对于上面的模型,P:C=1:1,消费者减无可减,所以也不可取。所以这个问题无解。仔细想 下,其实一个消费者而已也没有浪费太多性能。问题2:消费者消费能力跟不上生产者生产能力 这就引起了下面的设
2020-12-12 13:45:23 291
原创 Dubbo 连接模型及其原因
Dubbo的四个角色,服务提供者,服务消费者,注册中心,监控中心。Provider Consumer Registry之间两两连接而且都是长连接,Consumer Provider与Monitor之间的连接是短连接。为什么是这样的连接模型?答:Consumer Provider之间为什么是长连接的?Consumer Provider之间的连接是 单一 长连接。为什么这么设计呢?首先我们需要明白,两个进程之间可以建立多个连接,因为一个进程可以绑定多个端口。那么,两进程之间通信,单一连接与多连接有.
2020-12-10 21:14:58 273
原创 什么是RPC,RPC的好处
RPC: remote process call远过程调用,与之对应的是本地过程调用。RPC是将远过程调用进行了一层封装,使得使用者像调用本地方法一样调用远程方法。为什么要进行这样一层封装呢,或者这样说不进行这一层封装又会怎样呢?如果不封装,方法的使用者不会像封装后使用的那样方便,他需要自己来区分出来远程方法调用,对于远程的要采取与本地方法调用不同的手段来调用。但是使用者是不必关心这个方法是不是远程的,他只是像借用外部方法进行处理,然后拿到结果。所以,RPC那一层的封装减去了方法调用者不必要的额外工作
2020-12-10 20:02:55 1401
原创 为什么要有微服务
单体应用(仅一个进程)的优点:方便debug,最大的优点在初期方便代码开发,相比于拆分成各个不同的服务模块,需要定义好不同模块之间的交互规则缺点:在后期,代码量增大,每处改动改处的bug增大,迭代会变慢,而且每次迭代都需要整个应用重新部署。而微服务,只要保证各个模块间交互的接口不变。各个模块可以单独迭代,然后部署。可能仅仅是某块的访问压力增大,却需要将增大整个应用节点。而微服务可以就某个模块进行水平扩容。...
2020-12-10 19:54:15 316
原创 dubbo结合zk实现服务变更自动发现
主要依靠zookeeper的watch机制, watch+/dubbo/sericeName消费者会向zk注册一个watcher监听某一结点,两个要素,节点路径名和回调方法。zk会和provider保持心跳,如果provider失联,对应的node会被删除,或者新的provider上线会请求zk,在某一serviceName下建立一个新的节点。于是/dubbo/serviceName发生变动,触发watch机制,消费者端刷新provider信息...
2020-12-08 17:18:49 661 3
原创 Redis 主从复制原理
redis-master-slave-replication过程原理当从库和主库建立MS关系后,会向主数据库发送SYNC命令主库接收到SYNC命令后会开始在后台保存快照(RDB持久化过程),并将期间接收到的写命令缓存起来当快照完成后,主Redis会将快照文件和所有缓存的写命令发送给从Redis从Redis接收到后,会载入快照文件并且执行收到的缓存的命令之后,主Redis每当接收到写命令时就会将命令发送从Redis,从而保证数据的一致...
2020-12-07 19:56:58 103
原创 C++何时合成默认构造函数
先思考这么一个问题,有的时候C++要为一个类合成一个默认构造方法,或者扩充它的构造方法,为什么?合成默认构造方法或者扩充构造方法因为一个类在初始化时需要额外做一些事,比如建立虚方法表,初始化对象成员,这些操作是在新建一个对象的时候需要去做的,只是把他们都放在一起了,那个地方就叫构造方法。这篇文章有一个地方说错了,当有虚基类的时候,不是设置指向虚基类对象的指针,虚基类对象的数据也是和派生对象放在一起的。真正的原因是,虚基类也是基类,原因和基类是一样的。相关文章...
2020-12-02 18:38:23 236
原创 C++中的引用和指针
char a=’a‘;char* b=&a;//指针char& c=a;//引用C++中的引用声明时必须要赋值,而且其指向的地址不可更改。如果引用了一个对象的化,引用.相当于指针->.需要注意的是,通过汇编代码我们发现,一个字符类型的引用,无论是全局变量还是栈中的引用类型参数,其都有内存而且都是8字节,而那个字符是1字节。所以引用本身也是用指针实现的,只不过它不可更改存放的地址。另外引用没有二级或更高的引用。关于何时使用指针类型的参数何时使用引用类型的参数?感觉区别不大,
2020-12-01 22:04:23 92
原创 关于C++中虚函数实现原理的思考
网上对于C++实现原理大都讲到虚方法表这一层就结束了,感觉不是很痛快。下面讨论两个问题。虚方法的实现(多态)为什么非得运行时确定,或者说确定的到底是什么?一个虚方法对应的实现方法可能有多个,他们的地址都不一样,如果不在运行时确定,而是在编译时确定,那么地址一定是写死的只有一个,那肯定是有问题的。到底确定的是什么呢?想想函数调用的过程,栈上分配参数,保存返回地址,保存pc,设置pc,切换esp,ebp。是设置pc这一步非得运行时确定,即确定得时函数地址。2. 虚方法的原理落实到二进制文件到底是怎么实现
2020-12-01 20:24:57 104
原创 并发三特性(线程安全三特性)
为什么会提出这三个特性呢,就是说,如果某段代码不满足 原子性/可见性/有序性 那么就可能产生并发安全问题。原子性(我的理解):对于代码段,一次只允许一个线程执行可见性:变量被修改后,对其他线程立马可见有序性:代码禁止重排序违反原子性举例:首先我们保证可见性和有序性i++;多个线程同时执行上述操作违反可见性举例:if(i<0){ i++;}首先我们包证有序性和这块代码的原子性,即一次只允许一个线程执行。初始时,i=-1,线程A执行代码块,结果i变成0了,紧接着线程B执行
2020-11-29 20:03:47 357
原创 拓扑排序的证明
反证法首先,按照拓扑排序的规则失败了,即有A: { …->Ak } 对于剩下的节点B: {a,b,c,d…}无法被链到后面了假设这串节点是可以成功排序的,排序结果记为Y{…}那么Y中最早出现的集合B中的的节点记为node,我们可以确定node前面的所有节点一定都是在集合A里面的,那么我们可以发现这个节点是可以排在Ak后面的,矛盾!证毕...
2020-11-29 19:19:38 384
原创 AQS
AQS的核心是CAS尝试修改volatile变量state+一个双向队列管理线程。获取释放锁的原理(独占模式)关于那个唯一的活跃线程只有两种情况【1】头节点是活跃线程,或者活跃线程没有包装成节点同时没有等待节点【2】活跃线程没有包装成节点,头节点曾经是活跃线程,已经释放了资源第一种情况比较好理解,为什么会出现第二种情况呢,是因为允许非公平竞争资源的情况,最好的例子是ReentrantLock的非公平锁,它允许一个线程不检查是否需要排队直接尝试获取资源,这就有可能头节点唤醒next节点,但是因为
2020-11-29 16:54:42 491
原创 ConcurrentHashMap的size原理
jdk1.7 ConcurrentHashMap的size原理简而言之,累加各个segment的size,记为sum,统计两次,如果sum值相同且modnum(put,remove等都会进行加一操作)不变,则返回,否则,加锁重新统计jdk1.8 ConcurrentHashMap的size原理每次put时,cas加一,操作的对象有BaseCount和CounterCell数组(其长度未必和map中table一样长)。流程是先尝试对BaseCount进行cas加一,失败则通过Thread.prob
2020-11-27 22:03:02 437
原创 ConcurrentHashMap的get方法是最终一致性的
证明线程1在时间点A调用get,之后线程2在一个时间点B再次调用get查询,在两个方法返回之前,调用put方法,覆盖刚才的数据考虑这样的执行序列。1. 线程2读到数据,然后时间片用完2. put成功将数据覆盖 3. 线程1读到新数据,返回4.线程2拿到时间片,返回旧数据结果就是,线程1先返回拿到新数据,而线程2后返回拿到的是一个旧数据。说明ConcurrentHashMap的注释中已经说了,get方法只能保证看到之前完成的操作,无法保证看到正在进行中的操作。针对jdk1.7的concur
2020-11-27 21:28:44 1773
原创 CopyOnWriteArrayArrayList
写需要加锁,读不需要加锁,写的时候加锁,将旧数据copy到新的地方,旧数据依然可读,写完一键替换(volatile)然后释放锁。很好的博文,但是不认同CopyOnWriteList有数据一致性问题,他只是写比较耗时而已...
2020-11-27 20:13:11 327 1
原创 四种线程池的适用场景
很好的博文,但是我是很认可它对于cachedThreadPool的看法,我认为cachedThreadPool最大的特点应该是FixedBlockingQueue相对的,它适合每一时刻,任务数不固定的场景。当然我也赞同适合耗时短的任务,因为如果耗时长的话,哗来一堆任务,每个任务都得起一个线程...
2020-11-27 19:27:13 3447
原创 DelayedWorkQueue原理
使用最小堆实现,最近要到达时间的节点放在堆顶,每个节点都会附带到期时间,依次作为堆调整的依据。看poll()的源码就明白延迟队列的秘密了 public RunnableScheduledFuture<?> poll() { final ReentrantLock lock = this.lock; lock.lock(); try { RunnableScheduledFutu
2020-11-27 19:21:26 508
原创 ThreadLocal原理
线程本地变量,方便于同一线程内多个方法之间共享变量,同时可以避免其他线程访问到该变量。ThreadLocal对象最主要的方法就是set和get方法,其中set方法首先会获得当前线程然后拿到当前线程的threadLcoals变量,以当前threadLocal对象为key插入。get同理...
2020-11-27 19:04:24 151
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人