自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(44)
  • 收藏
  • 关注

原创 Golang 深度剖析 -- 理解Mutex源码实现

在golang的并发编程中,为了保证访问数据的安全性,经常会用到mutex去保证goroutine的同步,本文基于golang 1.14.6版本去分析mutex实现, golang中的mutex是一种排它锁,其实现结构如下:// A Mutex is a mutual exclusion lock.// The zero value for a Mutex is an unlocked mutex.//// A Mutex must not be copied after first use.ty

2021-02-24 20:31:15 347

原创 系统设计篇(三) -- 怎么设计高并发的服务(一)

高并发,高可用是服务端开发经常听到的词汇,在互联网应用中,随着用户的增加,后台服务需满足承载正常使用系统功能的用户数量。但是单机承载能力是有限的,因此通过多服务去支撑业务是必然的。但是不是所有业务都能通过简单的多服务扩展去解决,中间转换的过程会有很多问题,很多高并发服务的诞生并不是一蹴而就的,都是随着业务的扩展慢慢提高的,不同的场景遇到的问题也不一样,因此,在设计系统时需要因地制宜,根据当前业务场景去设计合适的架构。水平扩展 OR 垂直扩展网上听的最多的就是这两个词,垂直扩展好理解,就是提升单体服务的性

2020-11-01 13:47:33 429 2

原创 Golang 深度剖析 -- 理解Golang依赖注入

用过Java的都知道Spring框架,Spring核心是一个Ioc容器,各个模块都会注入到容器中,带来的优势是解耦,这样使得修改各个模块时不用管模块之间的依赖关系。举个例子,一个服务里面有日志模块,配置模块,DB模块,业务模块等,其中日志模块依赖配置模块,DB模块依赖日志模块,配置模块,业务模块依赖所有基础模块。这样带来的一个问题是,如果有模块要修改,势必会影响其他模块,如果模块很多,还需要人为的规定初始化顺序,这对大型项目的维护来说是一件很恐怖的事,因此依赖注入的引入可以减少维护依赖关系的精力,专心使开

2020-10-21 14:23:12 1429

原创 微服务系统设计篇(二) -- 如何做数据库选型

在微服务设计中,数据库的选型是不可缺少的一环,后台的核心是与数据打交道,在不同的业务场景选择的数据库不一样, 好的数据库选型能够解决业务的性能瓶颈,如果数据库选择不恰当,会使得服务的性能上不去,因此我们需要对一些常用的数据库有一些了解,这样才能因地制宜,发挥系统最好的性能。常见的数据库分类:数据库类型数据库名称关系型数据库Mysql,Oracle,postgresql内存数据库Redis,Memcache时序数据库TSDB文档型数据库MongoDB分布

2020-10-16 17:48:35 629

原创 微服务系统设计(一) -- 如何拆分服务

在做微服务设计的时候,很大的一个难题就是服务的拆分,很多人都不知道在什么情况拆分服务,在什么情况下不应该拆分服务,所以设计的系统可能会很臃肿,如果遇到业务扩展,之前设计的架构不能满足业务扩增后的需求,就会面临重构的风险,因此,在设计微服务架构时,合理的服务拆分是十分重要的。前提在做拆分服务之前,有一点特别重要,系统设计应该根据当前的用户情况而设计。如果目前用户不多并且增长比较慢,那么设计那些大而宽的架构并没有什么意义,单体服务就可以搞定,成本也比较小,并且可以满足早期的迅速开发和业务迭代需求,如果用户进

2020-10-13 16:09:35 1651 1

原创 Golang 深度剖析 -- Map的实现原理

Golang标准库实现了Map容器,在很多业务场景都会用到这个容器,但是使用不当有可能会出现问题,这里我们来探究Map底层到底是如何实现的。Map的实现在runtime/map.go,首先有这么一段介绍:// A map is just a hash table. The data is arranged// into an array of buckets. Each bucket contains up to// 8 key/elem pairs. The low-order bits of t

2020-10-12 09:30:50 653

原创 Golang 深度剖析 -- channel的底层实现

目录:channel 简介channel 内部结构创建channel发送数据接收数据关闭channel总结channel 简介Go语言有个很出名的话是“以通信的手段来共享内存”,channel就是其最佳的体现,channel提供一种机制,可以同步两个并发执行的函数,还可以让两个函数通过互相传递特定类型的值来通信。channel有两种初始化方式,分别是带缓存的和不带缓存的:make(chan int) // 无缓存 chanmake(chan int, 10) // 有缓存

2020-10-12 09:25:42 3063 1

原创 OpenTsdb驱动简单实现

时序时空数据库TSDB简介和使用方案可以看文档 [tsdb文档](https://www.docs4dev.com/docs/zh/opentsdb/2.3/reference) TSDB对外只提供restful api,而且TSDB作为时序数据库,在后台的微服务的使用大部分场景只做查询,数据的写入交由其他的数据采集服务负责。我们之前有个使用场景是通过canal去监听mysql binlog...

2019-07-19 16:08:43 497

转载 gRPC使用

首先安装protobuf和grpcgo get -u github.com/grpc/grpc-gogo get -u github.com/golang/protobuf/protogo-get -u github.com/golang/protobuf/protoc-gen-go //--go-out工具首先定义hello.protosyntax="proto3";option...

2018-09-20 14:18:02 622

转载 operator new和placement new的区别

new 关键字 (1)调用operator new分配足够的空间,并调用相关对象的构造函数 (2)不可以被重载operator new (1)只分配所要求的空间,不调用相关对象的构造函数。当无法满足所要求分配的空间时,则 ->如果有new_handler,则调用new_handler,否则 ->如果没要求不抛出异常(以nothrow参数表达...

2018-09-12 16:26:06 284

转载 #pragma once和#ifndef的区别

1)#ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况2)#pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。...

2018-09-12 14:21:16 567

转载 const 和 static的区别

static的作用:对变量:1.局部变量:在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。1)内存中的位置:静态存储区2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。注:当static用来修饰局部变量的时...

2018-09-12 13:34:54 2928

转载 内存读数据和磁盘读数据的区别

https://blog.csdn.net/zhanghongzheng3213/article/details/54141202/ 当程序要读取的数据时传入内存地址(行地址+列地址),如果数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,通过柱面号,磁头号,扇区号定位磁盘位置,找到数据的起始位置并向后连续读取一页或几页载入内存中。于存储介质的特性,磁盘本身存取就比主存慢很...

2018-09-12 13:13:16 4768

转载 tcp端口扫描方式

其实指TCP的连接方式 一般有三种: 1.通过connect 客户端通过connect发起连接后,如果服务器处于监听状态就可以发起连接成功,否则说明端口是关闭的。优点是比较简单可靠,缺点是如果连接不成功会频繁的发包,扫描时间比较长 2.通过SYN扫描 向目标端口发送SYN数据帧,如果又收到SYN+ACK说明开放,如果收到RST说明关闭,在IP层实现。 3.通过FIN扫描 四次挥手的过...

2018-09-11 14:40:57 4361

转载 c++类型别名

1、类型别名定义 类型别名(type alias)是一个名字,它是某种类型的同义词。使用类型别名有很多好处,它让复杂的类型名字变得简单明了、易于理解和使用,还有助于程序员清楚地知道使用该类型的真实目的。有两种方法可用于定义类型别名。 (1)传统的方法是使用关键字typedef:typedef double wages; //wages是double的同义词 typedef wages

2017-09-23 15:30:39 1466

转载 c++11实现的线程池

前言C++11之前我们使用线程需要系统提供API、posix线程库或者使用boost提供的线程库,C++11后就加入了跨平台的线程类std::thread,线程同步相关类std::mutex、std::lock_guard、std::condition_variable、std::atomic以及异步操作相关类std::async、std::future、std::promise等等,这使得我们编写

2017-09-15 19:12:19 405

原创 mmap和shmget的区别

二者本质上是类似的,mmap可以看到文件的实体,而 shmget 对应的文件在交换分区上的 shm 文件系统内,无法直接 cat 查看 安全性:mmap 方式对应的真实文件,如果用户有权限即可查看,甚至删除                  shmget 方式其实也一样,好了一层皮罢了(ipcrm -m …) 一致性:mmap 方式下各进程映射文件的相同部分可以共享内存

2017-09-04 22:21:33 4928

原创 abort,exit,return 的区别

exit(): 在调用时,会做大部分清理工作,但是决不会销毁局部对象,因为没有stack unwinding。 会进行的清理工作包括:销毁所有static和global对象,清空所有缓冲区,关闭所有I/O通道。终止前会调用经由atexit()登录的函数,atexit如果抛出异常,则调用terminate()。 abort(): 调用时,不进行任何清理工作。直接终止程序。 retrun:

2017-09-01 10:30:21 425

转载 setjmp 和 longjmp 函数使用详解

非局部跳转语句—setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。#include <setjmp.h>int setjmp(jmp_buf env);返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值的longjmp中的val值void longjmp(jmp

2017-08-25 23:23:25 434

转载 c++多重继承的bug

一个例子:#include <iostream>using namespace std;class Base1{public: virtual void foo1() {};};class Base2{public: virtual void foo2() {};};class MI : public Base1, public Base2{public: vir

2017-08-23 15:38:23 255

转载 拷贝构造函数的陷阱

拷贝构造函数大家都比较熟悉,通俗讲就是传入一个对象,拷贝一份副本。#include<iostream>using namespace std;class CExample {public: int a,b,c; char *str;public: //构造函数 CExample(int tb) { a = tb; b =

2017-08-23 13:52:37 212

原创 在 C++ 中子类继承和调用父类的构造函数方法

1. 如果子类没有定义构造方法,则调用父类的无参数的构造方法。 2. 如果子类定义了构造方法,不论是无参数还是带参数,在创建子类的对象的时候,首先执行父类无参数的构造方法,然后执行自己的构造方法。 3. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数,则会调用父类的默认无参构造函数。 4. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数且父类自己提供了无参构

2017-08-23 12:47:40 323

原创 第一个libevent程序

#include<sys/signal.h>#include<event.h>void signal_cb(int fd,short event,void* argc){ struct event_base* base= argc; struct timeval delay={2,0}; printf("caught an interrupt signal\n");

2017-08-17 13:05:03 200

转载 缺页中断

缺页中断   在请求分页系统中,可以通过查询页表中的状态位来确定所要访问的页面是否存在于内存中。每当所要访问的页面不在内存时,会产生一次缺页中断,此时操作系统会根据页表中的外存地址在外存中找到所缺的一页,将其调入内存。   缺页本身是一种中断,与一般的中断一样,需要经过4个处理步骤:   1. 保护CPU现场   2. 分析中断原因   3. 转入缺页中断处理程序进行处理

2017-08-15 13:31:37 659

原创 计算机是怎么做乘法运算的

通过加减法和移位来实现的;把除法转成乘法,乘法转成加法,减法也转成加法。模拟CPU运算乘法的步骤: 假设计算3*3 原码是0011 * 0011(以4位存贮单元,因为是原码,最高位不代表符号位) CPU中的乘法器过程如下: 3个寄存器分别存放乘数0011 被乘数 0011 一个部分积初始值为0 1、首先判断乘数寄存器(目前为0011)的最低位为1。如果为1则将部分积的值通过加法器加上

2017-08-14 23:27:30 25867 3

原创 c++并发指南-细说unique_lock

c++11有两种基本的锁类型,一种是lock_guard,一种是unique_lock,lock_guard使用十分简单,但是没有提供给程序足够的灵活度,所以c++11标准添加了Mutex RAII机制的另一个类unique_lock,使用也与lock_guard相似,但提供了更好的上锁,解锁的控制。 unique_lock对象以独占所有权的方式管理mutex对象的上锁和解锁操作。其他unique

2017-07-02 22:48:48 2475

原创 stl容器中移出元素的正确做法

我们知道在移出元素时,指向当前的迭代器会失效,如果要移出多个元素时,可以使用这种方法。我们看下面这段代码:typedef std::map<std::string,float> StringFloatMap;StringFloatMap coll;StringFloatMap::iterator pos;for(pos=coll.begin();pos!=coll.end();++pos){

2017-06-30 20:30:37 259

原创 map容器安插的方式

1,运用value_type 为了避免隐式转换,可以用value_type明白传递正确的型别。value_type是容器本身提供的型别定义,如:std::map<std::string,float>coll;coll.insert(std::map<std::string,float>::value_type("otto",22.3));2,运用pair<>std::map<std::strin

2017-06-30 20:01:03 154

原创 链接器如何识别重复模板实例

在两个cpp文件中都有一个相同的模板定义,并且都有相同实例,那么在main文件中调用这个实例会调用哪个模板实例呢?//文件名caller1.cpp#include<iostream>template<typename T>void func(T const &v){ std::cout<<"func1: "<<v<<std::endl;}void caller1(){

2017-06-26 18:16:55 219

转载 迭代器失效的场景

vector迭代器的失效的情况: 1.当插入(push_back)一个元素后,end操作返回的迭代器肯定失效。 2.当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时first和end操作返回的迭代器都会失效。 3.当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将

2017-06-26 16:23:56 802

原创 timer的用法

在c++中我们可以使用timer库来处理时间和日期,可以避免使用c中间的time.h的库函数。 timer是一个很小的库,提供简易的度量时间和进度显示功能,可以用于计时所需要的任务,timer包含两个组件:早期的timer(V1)和新的cpu_timer(V2),前者使用的是c/c++库函数,后者使用基于chrono库使用操作系统提供的API,精度更高,这里只介绍timer组件。 timer(V

2017-06-19 00:38:25 1270

原创 用c++实现一个二叉排序树

二叉排序树又称二叉查找树(Binary Search Tree)。其定义为:二叉排序树或者收空树,或者是满足如下性质的二叉树。 (1)若它的左子树非空,则左子树上所有节点的值均小于根节点的值。 (2)若它的右子树非空,则右子树上所有节点的值均大于根节点的值。 (3)左右子树本身又各是一颗二叉排序树。 二叉排序树数据结构如下://节点类定义class Node{ int dat

2017-06-19 00:06:45 1903

原创 unsigned int 和int 相加问题

今天下代码的时候遇到一个很有意思的情况,代码如下:#include<iostream>using namespace std;int main(){ unsigned int a=4; int b=-6; if(a+b>0) { cout<<"a+b为正"<<endl;; } else { cout<<"a

2017-06-17 22:37:03 657

原创 单例模式

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。 当例模式一般分为两种,一种是饿汉式单例,采取静态初始化的方式,它是由类一加载就实例化的对象,所以要提前占用系统资源。class final Singleton{ private:         Singleton(){};//构造函数声明为private,让外界无法利用new创建实例。

2017-06-17 16:30:36 239

原创 浅析linux网络编程基础API

linux网络API分为三个方面: (1)socket地址api。socket最开始的含义是一个IP地址和端口对(ip,port)。它唯一地表示了使用TCP通信的一端。称为socket地址。 (2)socket基础api。socket主要api定义在sys/socket.h这个头文件中,包括创立socket,命名socket,接受连接,读写数据,获取地址信息,检测带外标记,以及读取和设置sock

2017-06-09 00:31:51 347

原创 大小端字节序的区别

内存是以字节为单位读写的,其最小的读写单位就是字节。故如果在内存中写入一个字节,一个内存的存储单元便可以将其容纳了,只要访问这一内存地址就能完整的取出这一字节。但是一个字节只能够表示0~255(只考虑无符号数),超过这一范围的数只好用多个字节连在一起表示,因此,在我们32位程序中,定义的数据类型有很多,一字节的数据类型只有char型,像int要占四个字节,double要占八个字节,那么这么多个字节该

2017-06-06 22:06:24 906

原创 内存系统为什么要分段

内存按访问的方式来看,就像长方形的带子,地址依次升高。内存是一个随机读写设备,即可以访问内部任何一处,不需要从头开始找,只要直接给出地址即可,如访问内存0xc00,只要将该地址写入地址总线便可,而分段是内存访问的机制,是给CPU用的访问内存的方式,只有CPU才会关注段,那为什么CPU要关注段呢,原因如下: 编译器在编译程序时,肯定要根据CPU访问内存的规则将代码编译成机器指令,这样编译出来的程序才

2017-06-06 20:55:01 3489 1

原创 一个c/c++程序是怎么从代码到可执行文件的

我们以我们最初学到的“hello world”程序为例。这个程序在编译中是这样进行的,首先执行g++ helloworld.cpp命令得到a.out文件;执行./a.out命令就可以输出hello world!事实上执行g++ helloworld.cpp可以分为四个步骤,分别是预处理,编译,汇编,和链接,这就像一个被隐藏的过程,使用者可以通过简单的命令即可完成复杂的步骤。 一,预处理首先是源代码

2017-06-06 13:49:58 6227

原创 c++中如何实现一个不能被继承的类

方法一:用单例模式,这里不做阐述。 方法二:c++11标准提供关键字final。 方法三:友元加虚继承,这篇文章重点介绍这个方法。声明一个类A,构造函数声明为private,在类中声明友元类Bclass A{      private:           A(){};                 friend class B;};我们在让B虚继承Aclass B:virtual

2017-06-03 21:21:31 500

原创 vector的简单实现

#include<algorithm>#include<iostream>#include<assert.h>using namespace std;template<typename T>class myVector{ private: #define WALK_LENGTH 64 //myVector each time increase space le

2017-06-03 13:04:21 291

空空如也

空空如也

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

TA关注的人

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