- 博客(175)
- 资源 (6)
- 收藏
- 关注
原创 设计模式入门笔记
设计模式的定义:在软件工程领域,设计模式是一套通用的可复用的解决方案,用来解决在软件设计过程中产生的通用问题。它不是一个可以直接转换成源代码的设计,只是一套在软件系统设计过程中程序员应该遵循的最佳实践准则。
2023-08-28 17:16:42 1323
原创 设计一个feed流系统
移动互联网时代,Feed流产品是非常常见的,如朋友圈、微博、抖音等,除此之外,很多App的都会有一个模块,要么叫动态,要么叫消息广场,这些也是Feed流产品。只要大拇指不停地往下划手机屏幕,就有一条条的信息不断涌现出来。就像给宠物喂食一样,只要它吃光了就要不断再往里加,故此得名Feed(饲养)。
2023-06-19 14:54:29 1338
原创 ABTest基本原理(论文笔记)
参考论文:Overlapping Experiment Infrastructure: More, Better, Faster Experimentation参考翻译:https://blog.csdn.net/qq_34417408/article/details/116427639ABTest简介所谓 AB test,就是测试用户对某个产品同一个元素A和B两个版本(只有这个元素不同)的反应差异,从而进行后续取舍判断。互联网公司经常要上线各种各样的实验,例如修改UI界面的某个按钮,上线一个新的算法
2022-05-10 21:46:40 2320
原创 内存错误检测工具AddressSanitizer原理
原论文:AddressSanitizer: A Fast Address Sanity Checker谷歌官方文档:AddressSanitizerAlgorithm参考博客:Introduction to AddressSanitizer论文解读:AddressSanitizer论文解读Intro内存访问错误,简单地说就是访问了不该访问的区域。如果我们能够记录所有有效的内存区域,并且在访问内存之前进行检查,就可以有效地抓住这些bug。这篇paper介绍的AddressSanitizer (A.
2022-02-19 22:51:02 1397
原创 MySQL分库分表分区
数据库存储的演进单库单表单库单表是最常见的数据库设计,很多业务刚开始时都只需要单库单表,即数据存储只使用一个服务器结点,这个服务器上部署着一个数据库,数据库里对于每个存储场景只有一张表。(如果有多个服务器结点,就需要考虑分布式问题了,会使数据存储更加复杂。)比如说将所有订单数据存放在一张表里,那么所有的历史订单都可以在这张表上查到。但是随着时间的推移和业务的发展,数据表中存放的数据量越来越大,当数据量达到一定程度的时候,会影响到db的性能,因此可以考虑分区、分表、分库的方法来优化db的设计。其中,my
2022-01-27 20:22:02 2585
原创 Spark架构原理和生态系统
参考一文读懂 Apache SparkResilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing深入浅出理解 Spark:环境部署与工作原理一文弄懂Spark基本架构和原理Spark vs HadoopHadoop 是大数据处理领域的开创者,用于进行分布式、大规模的数据处理,其中MapReduce 负责进行分布式计算,HDFS 负责存储大量文件。Apache Spark
2022-01-17 15:39:04 3611 1
原创 mysql逻辑架构、查询过程和优化方法
参考 DBA整理的万字详解MySQL性能优化,值得收藏!MySQL执行计划解析MySQL语法执行工作原理 本文主要介绍MYSQL的逻辑架构和查询过程(数据库大多数都是读多写少,这里只关注查询过程,不讨论数据插入、更新等其他过程)MYSQL逻辑架构mysql逻辑架构分为三层:1、客户端:连接处理、授权认证、安全等功能(常见的登录、连接数据库之类的操作)。2、核心服务:查询缓存、解析、优化、执行计划、API调用存储引擎(API屏蔽了不同存储引擎间的差异)都在这一层。3、存储引擎:存储引擎负责M
2022-01-10 17:25:55 1030
原创 STL迭代器原理
参考C++ STL迭代器原理和实现迭代器STL(Standard Template Library)中提供了许多容器,包括vector、list、map、set等,少部分容器(vector)可以通过下标来访问其中的元素,而大部分的容器都不可以这么做,为了能够以一种统一的方式来访问STL的所有容器,STL提供了迭代器访问的方式,它的实现方式是在每个容器类中内嵌了一个专属的iterator类,在iterator类中实现了对该容器的元素的遍历和访问。通过在所有容器类中实现iterator,就可以很方便地实现
2022-01-07 15:25:46 1261 1
原创 Quartz分布式任务调度原理
什么是分布式定时任务调度定时任务调度在很多应用场景下我们需要定时执行一些任务,比如订单系统的超时状态判断、缓存数据的定时更新等等,最简单粗暴的方式是用while(true)+sleep的组合来空转,直到到达指定时间就执行任务,但这显然非常低效。更好的方法是使用系统提供的Timer定时器或者使用Quartz框架等等。持久化如果只是设置一两个固定的简单的定时任务,比如只需要定时把数据从磁盘更新到内存的缓存中,那不需要考虑太多,即使节点宕机了,重启后就会继续按原有频率继续执行定时任务,所以不需要考虑定时任
2021-12-31 20:12:35 9718
原创 无锁编程(CAS)
参考高并发之无锁编程多线程并发在高并发场景下往往需要用到多线程编程,又由于多个线程共享同一个进程中的地址空间,所以又可能会出现同时访问/修改同一个共享变量的情况,这就涉及到线程安全的问题,比如两个线程同时修改同一个数据,可能造成某线程的修改丢失;一个线程写的同时,另一个线程去读该数据时可能会读到写了一半的数据。对此,我们可以用锁来解决线程安全的问题,在访问共享变量的代码的前后加上加锁和解锁的操作,从而保证同一时刻只有一个线程处于临界区中访问资源。但是除此之外,还有一种无锁编程的方式也可以解.
2021-12-30 22:22:19 2448
原创 单例模式(C++实现懒汉式)
单例模式是设计模式中的一种,本文记录和总结单例模式的定义以及C++中实现单例模式的几种懒汉式方式。参考C++ 单例模式总结与剖析什么是单例模式单例(Singleton)模式的特点是这个类在全局只有唯一的一个实例对象,在所有位置都可以通过该类提供的接口访问到这个唯一实例。最经典的使用场景是公用缓存,由一个线程周期性地写,由多个线程读取,此时就可以用单例模式来保证不同线程写和读的是同一个实例。C++实现单例模式,有几个基础要点:保证全局只有一个实例。通过把构造函数设置为private可以防止用户
2021-12-30 19:45:58 3325 3
原创 超时重试机制
参考 https://zhuanlan.zhihu.com/p/115918351数据从起点数据库【上游】,经过数据处理层、数据传递层、数据应用层到终端【下游】用户。RPC 请求的结果有三种状态:成功、失败、超时。数据库超时数据库超时的情况:业务模块在某些时间段可能会出现对数据库的请求量过多的情况,数据库机器会因为CPU打满而无法提供服务,大量请求都超时了,此时最大的问题往往是慢SQL,分析慢SQL日志可以找出问题并且解决。我们平时写访问数据库的代码时,可以考虑优化:评估SQL语句的执行时间,
2021-12-28 21:41:44 1375
原创 栈帧原理介绍
基础知识进程中的栈区(stack)用于维护函数调用的上下文,没有栈就没法实现函数调用。栈用于存放函数(包括main函数)里的局部变量,函数调用时要传递的参数等。在进程的内存空间中,栈是向下生长的,即栈底在高地址,栈顶在低地址,栈底固定住,栈从内存高地址->低地址的路径延伸。栈帧(stack frame):每一次函数调用时,都会在栈上为这次函数调用维护一个独立的栈帧。一个栈帧由两个寄存器来界定:ebp:指向栈底的指针,称为帧指针(Frame Pointer)esp:指向栈顶的指针,称为栈指针
2021-12-28 21:39:25 1166 1
原创 分布式锁(redis、zookeeper)
参考分布式锁用 Redis 还是 Zookeeper?分布式锁当一个单点机器上有多个进程或者多个线程需要互斥访问一个共享资源时,就需要用到锁,这种情况下,只需要用各个编程语言库的锁即可,比如C++的pthread_mutex_lock,Java的synchronized和ReentrantLock等等来加锁。但是本机的锁只能被本机的进程访问,而现实中的许多业务的访问量一般都比较大,单点机器无法支撑,必须多点部署,此时如果不同机器上的进程/线程仍然需要互斥访问一个全局的共享资源的话,就必须使用分布式锁,
2021-12-28 21:36:07 1474 1
原创 mysql类型char, varchar和text的区别
程序中的string类型,在mysql数据表中可以有三种对应的类型:char、varchar和text。char、varchar和text的区别char:定长字符串,最大长度255字节,不足255字节的部分用空格补齐,数据库检索出char类型的数据表数据时会自动截断后面的空格,也就是说字符串后面自带的空格也会被删掉,使用要小心。定长的好处是存取更高效。varchar:可变长字符串,最大长度65535字节,例如: 当varchar(10)字段类型中插入"abc"时,实际存储大小也只有3个字节,此外,va
2021-12-14 12:06:05 1381
原创 git教程笔记
git教程:https://www.liaoxuefeng.com/wiki/896043488029600/896067008724000下面的笔记只简单记录git的一些原理,不记录具体的命令,有需要的时候再网上查具体的执行命令。(博客图片放在github图床上,网络能访问github的情况下才看得到图片哦)git简介git是一个分布式的版本控制系统,最初由Linux的作者Linus用两周时间用C语言开发出来,用于管理Linux源码,方便Linux社区的志愿者为Linux贡献代码。随后github
2021-12-10 18:02:58 1150
原创 Typora+PicGo+GitHub插入图片自动上传图床
Typora是一个非常好用的markdown编辑器,其所见即所得的风格以及全桌面平台支持的特性使其备受欢迎,不过插入图片一直是它的一个缺点,不如说插入图片一直都是markdown的一大缺点:本地编辑时,需要先将图片保存在一个目录下,然后再复制它的路径到markdown文档里,才能将图片显示出来,而一旦把图片搬到别的路径下,就又要到markdown文档里逐个修改图片路径,非常繁琐。将markdown文档作为博客发布到网上时,由于图片还保存在本地,网上肯定访问不了个人电脑本地路径下的图片,因此又要一张张.
2021-12-08 15:26:27 1105
原创 C++ RapidXml快速入门
参考官方教程:http://rapidxml.sourceforge.net/manual.htmlRapidXml是C++的一个读写xml文件的库,这里摘抄其中的第二章,2分钟快速指引。xml:可扩展标记语言DOM:Document Object Model2.1 Parsing从一个string类型的文本解析出一棵DOM树using namespace rapidxml;xml_document<> doc; // character type defaults to c
2021-12-07 16:13:01 962
原创 const指针和指向const的指针
今天在看项目代码时,发现竟然可以给有const修饰的指针赋值,按道理的话,const修饰的不是常量吗?常量应该是初始化之后就不能再修改才对。对于这个问题,我大致的研究了一下。参考const 指针与指向const的指针 const的理解、const指针、指向const的指针首先对于普通的const常量,必须在声明的时候初始化,否则会报错。const int a = 100;而对于const指针来说,根据const与*的相对位置,可以分成三种不同的情况: const指针:const关健字
2021-10-09 21:52:09 2765 1
原创 Embarrassingly_Simple_Binary_Representation_Learning阅读笔记
https://github.com/zhongzhh8/PaperReading/blob/master/Embarrassingly_Simple_Binary_Representation_Learning%E9%98%85%E8%AF%BB%E7%AC%94%E8%AE%B0.md
2021-02-27 22:18:00 185
原创 pytorch指定GPU后仍旧使用GPU0的解决方法
我在训练模型的时候,已经指定了使用GPU5、6进行训练,然而pytorch却强行在GPU0里占用100多M的空间,但是刚好GPU0被别人占满了,导致一直是CUDA:out of memory的状态.这个问题跟为什么Pytorch死活要用第0块显卡–我和pytorch的恩怨情仇非常像,但是我用他的方法根本不管用,感觉我的情况跟他的应该是不相同的,所以我只能自己找问题。我根据错误提示,发现溢出的语句是加载预训练模型参数的地方:rnet_checkpoint = torch.load('../s_resne
2020-12-03 19:21:54 12945
原创 互联网面试常见智力题
楼层丢鸡蛋有2个鸡蛋,从100层楼上往下扔,以此来测试鸡蛋的硬度。之前有看过,似乎比较好的方法是取平方根sqrt(n),从下往上,每sqrt(n)层楼丢一次,直到一个鸡蛋碎了。然后再从上一次没碎的地方开始向上逐层遍历。这样比较均衡,最好情况是在第10层碎掉,尝试次数为 1 + 9 = 10次。最坏的情况是在第100层碎掉,尝试次数为 10 + 9 = 19次。最好的方法是动态规划,比较复杂,这里就不看了。最优解,解方程法:假设要尽量使得最坏情况下扔鸡蛋的次数也是最少的。假设最坏情况下要扔x次,那么
2020-10-22 15:00:35 2010
原创 mysql回滚日志与重做日志
基础知识:数据都是先读到内存中,然后修改内存中的数据,最后将数据写回磁盘。这里把数据库内容在磁盘上的部分叫data file,把数据库内容在内存中的缓存叫data buffer。data buffer与data file内容不同,此时把data buffer的内容叫脏数据,但是不能每次事务提交时都同步到磁盘,这样磁盘IO开销太大,应该等到data buffer内数据比较多时再全部更新到磁盘。这里把日志磁盘上的文件叫log file,把日志在内存上的缓存叫log buffer。log buffer与log
2020-10-22 01:03:59 1658
原创 数据库隔离级别与MVCC多版本并发控制
数据库隔离级别这部分主要看的是ACID特性中的隔离性。隔离级别越高,事务越安全,但是并发性会变差。数据库的三种隔离问题:脏读:事务A更新了数据,但未提交,事务B读取了这个更新后的数据。随后事务A回滚,结果导致事务B读取的是脏数据,因此叫脏读。不可重复读:事务A对同一个数据先后读两次。第一次读取完毕后,事务B更新了这个数据,随后事务A进行第二次读取,发现这个数据转眼间竟然前后不一致。这就是不可重复读。(重点在修改)幻读:事务A查询或者修改数据表的符合范围条件的数据记录,但期间事务B向表中这个范围内
2020-10-22 01:02:27 248
原创 MySql索引详解
索引是数据库里的一个用于排序的数据结构,查询语句使用到索引的时候,就不需要扫描整张表去查找数据,可以提高查询的速度。但是创建和维护索引需要耗费一定的时间,同时也会影响插入的速度。mysql主要使用B+树作为索引结构。mysql的索引结构主要有hash索引和B+树索引两种,hash索引是基于hash表实现的,缺点很多,所以B+树索引更常用。hash索引缺点:1.无序,则无法排序,范围查询开销大;2.key值重复率高时,出现大量哈希冲突,拉链很长,索引效率接近于遍历。聚集索引 vs 非聚集索引聚
2020-10-22 01:00:48 111
原创 冒泡排序(优化)、快速排序、归并排序和堆排序
冒泡排序原始版本,每次对比相邻元素,把更大的元素换到右边,则每轮比较可以将当前最大的元素移动到最右边,下一轮比较不用比较最后面已经有序的元素。#include <iostream>using namespace std;int main() { vector<int> a; //初始化 for(int i=0;i<a.size()-1;i++) { bool sorted = true; for
2020-10-22 00:58:13 1194
原创 TCP三次握手和四次挥手
参考面试官,不要再问我三次握手和四次挥手TCP三次握手在socket编程中,客户端执行connect()时,将触发三次握手。三次握手状态图需要注意的是:客户端和服务端的状态变化。发送报文的SYN、ACK标志。报文的seq和ack序列号。首先服务端创建socket,然后用bind函数绑定端口号,再调用listen函数去监听这个端口。客户端这边创建socket,然后调用connect函数去与服务端对应的端口建立连接(期间有三次握手,半连接队列的内容)。连接成功后服务端调用accept函.
2020-10-22 00:56:17 100
原创 socket简介
简单理解Socketsocket是网络编程的一个概念,使用户更方便的使用底层的协议。socket 其实就是一个五元组,可以标识一条可用的连接。源IP, 源端口, 目的IP, 目的端口, 类型(TCP or UDP) 比如[110.122.144.166:45678, tcp, 110.88.92.104:80] 源IP为你的出口IP地址 110.122.144.166,源端口为随机端口45678目的IP为百度的某一个负载均衡服务器IP 110.88.92.104,端口为HTTP标准的80端口
2020-10-22 00:54:49 1269
原创 redis优化(bigkey、hotkey)
bigkey优化什么是bigkeybigkey是指某个key的value太大,分成两种情况字符串类型:它的big体现在单个value值很大,一般认为超过10KB就是bigkey。比如说把文章正文甚至小说全文都缓存进redis了。非字符串类型:哈希、列表、集合、有序集合,它们的big体现在元素个数太多。比如通过hash的方式来存储每一天用户订单次数。其中key = 日期,field = 用户id,value = 用户订单数。那么如果一天有上千万个用户下订单,那么field就会非常多,存储空间也很大,
2020-10-22 00:51:32 1209
原创 redis持久化机制
redis有两种持久化机制:RDB(快照)和AOF(日志)COPY ON WRITE机制:当前数据正在进行处理(比如制作快照或者进行AOF重写)的时候,如果有新的请求需要修改数据,那么就用到了写时复制技术。即将数据复制一份出来,然后在复制的数据上面进行修改。等到前面的处理流程结束后,可以把这份复制出来的数据写回去,或者直接指向这块新的内存。父进程fork子进程的时候,用到COW,意思是,原本新fork出来的子进程是共享父进程的数据的,只有当父进程或者子进程修改数据的时候,才复制一份出来,在复制的数据上
2020-10-21 20:00:16 175
原创 redis分布式(三种模式)
主从模式(读写分离)作用是:主从复制:备份数据,即使部分节点损坏也可以恢复。读写分离:主节点负责写,从节点负责读。因为读事务比写事务多很多,所以把读事务交给多个从节点来负责,可以减轻主节点压力,提高效率。缺点:主节点宕机后,无法提供写事务,也无法重新选举主节点。哨兵模式哨兵模式建立在主从模式上,作用是当主节点宕机后,哨兵负责在slave中选一个成为新的主节点,当原本的主节点恢复后,就成为了从节点。使用哨兵,相当于客户端不是直接访问Redis服务,而是先访问哨兵系统,哨兵告诉客户端哪个才是
2020-10-21 19:59:01 3068
原创 redis的5种数据结构及其底层实现原理
redis中的数据结构Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(无序集合)及zset(有序集合)。在秒杀项目里,我用过redis的Set和Hash结构:String:一个 key 对应一个字符串,string是Redis 最基本的数据类型。(字节的abase框架只实现了redis的string数据结构,导致我们如果想要存储复杂的数据结构的时候,只能转成json格式的字符串来存储)list:一个 key 对应一个字符串列表,底层使用双向链表实现
2020-10-21 19:55:43 30123 4
原创 redis为什么使用单线程模型
redis单线程模型如下:redis基于内存,速度很快。相比单线程读写内存的时间,读写同样大小的数据,使用多线程所带来的上下文切换开销就显得不可忽略,所以说redis使用单线程可以避免上下文切换的开销。相比之下,对于数据库这种磁盘读写的应用来说,读写磁盘的时间远大于多线程上下文切换时间,因此更适合使用多线程。不必考虑线程安全问题。很多操作都不用加锁,提高了性能,而且设计上更简单;所以作者说单线程就够快了,没必要写多线程。(redis本身有很多线程,redis单线程指的是只有一个线程从队列取出网络
2020-10-21 19:53:42 207
原创 Golang GMP机制
调度机制goroutine是go里的最基本的执行单元,每个go程序一开始都有一个主goroutine。goroutine可以认为是轻量级的用户态线程,go里内核线程和用户线程的调度模型是M:N模型。但是Go不直接将内核线程与goroutine绑定起来运行,而是通过一个上下文P来作为调度的中介,P提供了goroutine运行所需的一切资源和环境,所以在goroutine看来P就是运行它的 “CPU”。一个内核线程M维护一个P,一个P维护一个本地G队列,同一时刻里,一个P里只有一个G在运行。当通过g
2020-10-21 19:51:16 727
原创 C++11 右值引用
右值引用的目的主要是为了是减少内存拷贝,优化性能。左值右值赋值操作符“=”的左侧,通常是一个变量赋值操作符“=”的右侧,通常是一个常数、表达式、函数调用表达式结束后依然存在的持久化对象表达式结束时就不再存在的临时对象左值可以运用&操作符取得地址右值(临时对象)无法取得地址左值一般有名字右值一般没有名字C++11以前,就有左值引用,简称引用,左值引用就像是给变量起了别名,操作这个别名就跟操作原变量名一样。int x = 20;int&
2020-10-21 19:49:00 403
原创 C++11智能指针
使用new和delete来管理内存,容易出现问题,比如忘记delete、程序异常or过早返回导致没有运行delete之类的。智能指针的使用方式跟常规指针一样,最大的区别是它会自动释放所指向的对象。因为智能指针是一个类,当这个对象的生命周期结束时会执行析构函数,那么只要在析构函数中delete 指针就可以自动完成内存的回收。主要有两个指针:shared_ptr允许多个指针指向同一个对象,unique_ptr则“独占”所指向的对象。shared_ptr创建智能指针(为空):shared_ptr<s
2020-10-21 19:48:26 93
原创 C++ 虚函数与多态
虚函数虚函数是指在多态中,派生类和基类中存在返回类型、名字和参数形式都完全相同的函数,但是实现的函数体不同。虚函数是多态的基础,没有虚函数就无法实现多态特性。在成员函数前加上一个virtual关键词就可以把函数设置为虚函数 ,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。纯虚函数就是声明后面加上 =0 。virtual void foo()=0;纯虚函数在基类中只声明不定义,而在派生类中必须要定义。拥有纯虚函数的类成为抽象类,抽象类不能实例化。虚函数的实现原理当一个类
2020-10-21 19:47:11 394
CCV下载方法.txt
2019-08-31
C++矩阵运算模块
2018-04-09
《机器学习实战》pdf及所附python代码和数据集文件
2018-04-06
逻辑回归算法C++代码及实验数据文件
2018-04-02
决策树代码及实验数据文件
2018-04-02
云计算MapReduce实现KNN算法
2018-04-02
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人