- 博客(34)
- 收藏
- 关注
原创 mysql连接池
一、mysql连接池步骤:1、初始化连接,初始化的连接数,可以参考公式:连接数 = (CPU核数 * 2) + 有效的磁盘数。一个4核i7的处理器,它的数据库连接数可以设置为 4*2+1 = 92、线程池从连接池里拿到连接,这个过程是加锁的3、使用连接,执行sql操作4、处理完sql之后,将连接放回到连接池里注意的点:a) mysql的重连在初始化的时候,需要设置mysql_option函数的,重连参数。之后,在操作数据库的每个接口中,需要加入mysql_ping, 检查连接是否正常。
2021-10-20 22:23:25
380
原创 分布式锁的实现与原理
1、基于数据库实现的分布式锁缺点:a. 因为数据库需要落到磁盘上,有磁盘IO的消耗,所以性能没有下面两个高。b. 数据库没有定时释放锁,如果获得锁的进程挂了,那么就会造成死锁。2、基于缓存redis实现的分布式锁a. 通过setnx来实现分布式锁。 setnx是在key值不存在的时候,才能设置成功的。b. redis数据库可以给超过设置的锁,进行释放,通过setex.c. setnx 和setex 需要合二为一,是原子操作。在redis2.8之后的set,操作,可以通过设置参数,“ex”, “
2021-10-20 22:13:07
146
原创 CAS无锁消息队列
1、简介在进入今天的主题之前,我们先来了解一下一般使用的比较常用的锁。互斥锁和自旋锁。互斥锁:如果取不到锁就会进入休眠,本身取锁的操作并不耗时,主要就是等待拿到锁的时间,并且这样的话会进行线程切换,比较耗资源;自旋锁就不一样了,在没有获取到锁的情况下不会休眠,而是一直忙等待下去,一直占据CPU,不进行线程的切换,这样的好处就是执行本身耗时比较短的操作时,加锁的代价比较小,但是如果本身加锁执行的操作很长或者会有可能阻塞的话,其他锁一直忙等也是很耗CPU的。首先需要先了解一下CAS无锁队列的概念。CAS的
2021-07-21 21:48:30
317
原创 reactor与单台服务器并发
reactor单反应堆实现百万并发1.对并发概念的理解服务器并发概念:服务器同时能承载的客户端数量。服务器并发的基本要求:(1)5w以上的响应请求, 这些请求,可能是对数据库的操作,磁盘的操作。(2)cpu占用率在60%左右(3)内存占用率在80%左右对并发理解的误区:(1)QPS:服务器每秒的吞吐量(2)服务器处理客户端请求的数量 -----> 没有限定时间2.五元组保证唯一的网络 IO五元组定义 描述源IP 客户端IP目的IP 服务端IP源端口 客户端port:0~65
2021-07-19 22:20:35
202
原创 定时器的设计
实现定时器的结构实现定时器的底层结构,一般有1、红黑树2、时间轮3、跳表4、最小堆定时器的作用1、超时控制2、定时任务问一下,想要实现一个定时器,数据结构需要具备哪些特性?插入数据的时候,查找和插入的速度都得要快才行(时间复杂度)同时要保证,结构的有序性跳表实现定时器redis中的zset类型, 当插入的元素个数超过128个时,用跳表来实现的。那么redis的定时器时怎么实现的,redis是用无序的双端链表来实现的定时器的。但作者说了,这种无序的双端链表的时间复杂度为O(N
2021-07-12 18:07:44
962
原创 用户态协议中之epoll的实现
1、在网络编程的时候,有以下这些接口,socket 、listen、 bind、 accept、recv、 send、 close、connect ````请问有哪些接口,被调用的时候,会给对端发送一个数据呢?send、connect、close2、 epoll 需要检测哪些地方?1)accept队列有了节点,即三次握手成功, 就会回调epoll2)客户端发送数据到tcp协议栈的时候,且返回了ACK给客户端的时候,回调epoll3)tcp协议栈调用了send函数, 给客户端发送消息之后 ,tc
2021-07-11 23:04:57
211
原创 TCP/IP、拥塞、慢启动
用户态协议栈TCP/IP 滑动窗口 拥塞慢启动为什么普遍使用TCP?TCP协议头如何保证必达,有序3次握手TCP 11种状态转化图TCP怎么保证高效TCP 是怎么保证顺序的?为什么还有UDP传输?拥塞控制是怎么样的?如果遇到拥塞,滑动窗口怎么算?RTT怎么计算?TCP四次挥手为什么普遍使用TCP?1、数据可靠、必达2、传输效率不低3、顺序TCP协议头每个TCP包,都会有这个协议头。问:sequence Number 的初始值是多少?有没有可能有溢出的现象?答:sequence num
2021-07-10 13:05:43
174
原创 用户态协议栈TCP/IP的实现
在上一篇文章中,知道了为什么要有用户态协议栈,它具备什么功能。今天来讲述,如何实现一个用户态协议栈。它的原理就是, 将TCP/UDP到达网卡经解析后的数据,存储起来, 然后存储的位置通过映射的方法,直接到达应用程序处理。网络协议栈请问,网卡是属于哪一层协议栈?先解释一下,物理层 传输的是 物理信号, 即 光电信号。数据链路层 , 对应的是 数字信号。而从物理层的 光电信号 转化为 数据链路层的 数字信号, 靠的是 网卡。网卡, 也可将 数字信号转为 光电信号。所以,网卡并不属于网络协
2021-07-09 16:35:06
819
3
原创 用户态协议栈基础知识
每一个客户端给服务器发送数据时,都会先经过服务器的网卡,通过网卡解析之后,然后网卡有一块数据,能够把解析后的数据存储起来。接着,再从网卡存储的数据拷贝到内核协议栈,最后,再从内核协议栈拷贝到应用程序。...
2021-07-08 11:00:01
494
原创 epoll 的 reactor模型
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/epoll.h>#include <arpa/inet.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#define BUFF
2021-07-06 20:59:18
185
转载 正确的理解MySQL的索引机制以及内部实现(一)
本文链接:https://blog.csdn.net/SnailMann/article/details/88594860 正确的理解MySQL的索引机制以及内部实现(一) 如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!博客目录 | 先点这里 第一部分 倾向于My
2021-07-04 17:00:36
264
转载 MVCC多版本并发控制
所以我们知道 Read View主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个Read View读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。...
2021-07-04 16:48:55
237
原创 sentinel哨兵集群与redis集群
哨兵主要任务Redis 哨兵机制是实现 Redis 不间断服务的高可用手段之一。主从架构集群的数据同步,是数据可靠的基础保障;主库宕机,自动执行主从切换是服务不间断的关键支撑。Redis 哨兵机制实现了主从库的自动切换:1) 监控 master 与 slave 运行状态,判断是否客观下线;2) master 客观下线后,选择一个 slave 切换成 master;3) 通知 slave 和客户端新 master 信息。哨兵集群原理为了避免单个哨兵故障后无法进行主从切换,以及为了减少误判率,又引
2021-07-04 15:48:08
116
原创 redis持久化
思维导图内存快照在redis执行 “写指令”过程中,内存数据会一直变化。所谓的内存快照, 指的是 Redis内存中的数据在某一刻的状态。像拍照一样,通过照片就能把某一刻的瞬间画面完全记录下来。redis与之类似,把某一时刻的数据以文件的形式拍下来,写到磁盘上。这个快照文件就叫RDB文件。 (redis DataBase)redis通过定时执行RDB内存快照,这样就不必每次执行「写」指令都写磁盘,只需要在执行内存快照的时候写磁盘。既保证了唯快不破,还实现了持久化,宕机快速恢复。生成RDB策略Re
2021-07-04 14:19:19
86
原创 redis常用的操作
基本数据结构string字符串1) 字符串的值既可以存储文字数据,又可以存储二进制数据2)MSET\MGET 命令可以有效地减少程序的网络通信次数,从而提高程序的执行效率3)redis用户可以定制命名格式来提升redis数据的可读性并避免冲突。应用举例:缓存热门图片:set redis-log.jpg redis-log-data存储文章文章长度计数功能、文章摘要、文章计数文章长度:strlen article:10086:content文章摘要: getrange article:
2021-07-04 12:00:17
79
原创 高性能的redis
完全基于内存实现Redis是基于内存的数据库,跟磁盘数据库相比,完全吊打磁盘的速度。对比一下,内存操作和磁盘操作的差异内存操作 是由CPU控制的,也就是CPU内部集成的内存控制器,所以说内存是直接与CPU对接,享受最优的带宽。redis 将数据存储在内存中,读写操作不会因为磁盘的IO速度限制,所以速度飞一般的感觉。高效的数据结构Redis常用的五种数据类型和应用场景string 缓存、限制器list 链表、队列,朋友圈hash 用户信息、hashset 去重、投票、共同好友zse.
2021-07-04 10:15:46
123
原创 redis底层数据结构
调试redis的命令cd redis-6.0.0 – 进入redis目录redis服务器端 启动gdb、redis1、gdb --args ./src/redis-server redis.conf2、设置断点 b 文件名:函数名3、输入 c等待客户端触发断点redis的结构Redis 整体就是 哈希表来保存所有的键值对,无论数据类型是 5 种的任意一种。哈希表,本质就是一个数组,每个元素被叫做哈希桶,不管什么数据类型,每个桶里面的 entry 保存着实际具体值的指针。
2021-07-03 22:46:04
94
原创 redis源码分析 -- scan分步遍历
字典中的hash表遍历的方式有以下几种:keys、hkeys、scan、hscan、zscan。全遍历:keys和hkeys返回的是hash表中的所有的key,如果当前的hash表很大的话,会比较耗时,这样的话就会阻塞其他操作,因此运行环境中返回keys和hkeys这两种方式是不推荐的。分步遍历使用scan是分步遍历的,是分步进行返回的,这样就不会阻塞其他的操作。scan的用法scan 0 match * count 1 – 第一次scan, 输入的游标是0,然后根据返回的下一个游标数字
2021-07-03 17:34:33
341
原创 nginx源码解析-内存池
内存池的概念(Memory Pool)是一种内存分配方式,又被称为固定大小区块规划(fixed-size-blocks allocation)。通常我们习惯直接使用new、malloc等API申请分配内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。内存池则是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。这样做的一个显著优点是,使得
2021-07-03 16:58:16
118
原创 网络IO管理
5种网络IO模型1、非阻塞IO2、阻塞IO3、多路复用IO4、异步IO5、信号驱动IO信号驱动IO#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#include <unistd.h>#include <signal.h>#in
2021-07-01 15:54:10
104
原创 内存池设计
#简易版的内存池设计#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#define MP_ALIGNMENT 32#define MP_PAGE_SIZE 4096#define MP_MAX_ALLOC_FROM_POOL (MP_PAGE_SIZE-1)#define
2021-07-01 11:50:39
92
原创 手撕线程池
线程池通过使用线程池,我们可以有效降低多线程操作中任务申请和释放产生的性能消耗。特别是当我们每个线程的任务处理比较快时,系统大部分性能消耗都花在了pthread_create以及释放线程的过程中。那既然是这样的话,何不在程序开始运行阶段提前创建好一堆线程,让他们处于休眠等待状态。等我们的任务需要被执行的时候,把任务往线程池里放入,并唤醒线程池里的线程。任务执行完了,线程再次处于休眠状态。线程的主要作用:异步解耦,解决了阻塞IO,线程创建销毁成本问题线程池可以应用于,打印日志。写日志到磁盘的时候,
2021-07-01 11:10:52
170
原创 布隆过滤器
#include "bloomfilter.h"#include <stdio.h>#define MAX_ITEMS 6000000 // 设置最大元素个数#define ADD_ITEMS 1000 // 添加测试元素#define P_ERROR 0.0001 // 设置误差int main(int argc, char** argv){ // 1. 定义BaseBloomFilter static Base.
2021-06-04 22:29:35
142
原创 如何启动一个lua服务
最近在看公司项目的代码,发现了一个问题。skynet.newservice(“xxx”); 写的是xxx, 是一个目录的名字,而目录名下面有一个main.lua。 启动的正是这个main的脚本。因为在之前skynet api的学习中, skynet.newservice,传入的的参数都是要启动的服务的脚本名字的。那为啥项目里传入的参数是目录名了。带着这个问题,有必要深入地去看一下skynet 是如何启动一个lua服务的。每个skynet进程在启动时,都会启动一个lua层的launcher服务,该服务
2021-05-21 14:20:35
729
转载 lua与c之间交互详解(三)
本篇主要讲解Lua是如何调用c的,Lua是宿主语言,c是附加语言,关于c如何调用Lua参考其他两篇。Lua调用c有几种不同方式,这里只讲解最常用的一种:将c模块编译成so库,然后供Lua调用。gcc mylib.c -fPIC -shared -o mylib.so -I/usr/local/include/约定:c模块需提供luaopen_xxx接口,xxx与文件名必须一致,比如"mylib";还需提供一个注册数组(55-60行),该数组必须命名为luaL_Reg,每一项是{lua函数名,c函数名},
2021-05-14 14:43:40
215
转载 lua与c之间交互详解(二)
本篇主要讲解下c如何调用Lua的,即c作为宿主语言,Lua为附加语言。c和Lua之间是通过Lua堆栈交互的,基本流程是:把元素入栈——从栈中弹出元素——处理——把结果入栈。关于Lua堆栈介绍以及Lua如何调用c参考其他两篇。加载运行Lua脚本通过luaL_newstate()创建一个状态机L,c与Lua之间交互的api的第一个参数几乎都是L,是因为可以创建多个状态机,调用api需指定在哪个状态机上操作。lua_close(L)关闭状态机。复制代码int main(int argc, char *
2021-05-13 14:47:04
604
转载 lua与c之间交互详解(一)
lua与c之间交互是通过“lua堆栈”通信的。不管是lua调用c还是c调用lua,都是通过操作lua堆栈实现的。顾名思义,lua堆栈也满足后进先出的特点,入栈/出栈都围绕栈顶进行的。与通用的栈不同的是,这个虚拟栈每个位置都对应一个索引,可以通过索引操作指定位置的数据。1代表栈底,向栈顶依次递增;-1代表栈顶,向栈底依次递减,如图。lua中类型在c中如何表示要实现c和lua之间的交互,先了解下lua中基本类型与c中类型怎么对应的。lua中有八种基本类型:nil、boolean、number、strin
2021-05-13 14:42:47
480
原创 B树与B+树
B树的性质一颗M阶B树T,满足以下条件1.每个节点至多拥有M颗子树2.根节点至少拥有两颗子树3.除了根节点以外,其余每个分支结点至少拥有M/2颗子树4. 所有的叶节点都在同一层上5. 有k课子树的分支结点则存在k-1个关键字,关键字按照递增顺序进行排序6. 关键字数量满足ceil(M/2)-1 <= n <= M-1B树的作用磁盘存储,是采用B树的结构。磁盘的一个扇区,相当于B树的一个节点。使用B树,存储的层数降低了,使得查找性能的效率提升了。B树的添加1.先判断结点里的关
2021-05-11 22:52:55
247
原创 234树与红黑树
红黑树删除一、自己能搞定 对应叶子节点是3节和4节点二、自己搞不定,需要跟兄弟借,但是兄弟不借,父亲下来,然后兄弟找一个人代替父亲当家三、跟兄弟借,兄弟也没有
2021-04-30 15:09:11
1329
原创 skynet 服务调度
skynet.sleep(time)让当前任务等待time * 0.01sskynet.fork(func, …)启动一个新的任务去执行func, 相当于开了一个协程,函数调用完返回线程句柄。 每次调用skynet.fork ,都是从协程池中获取未被使用的协程,并把协程放入到fork队列中,等待一个消息的调度,然后会把fork队列中的协程拿出来执行一遍,执行结束后,会把协程重新丢入到协程池中,这样避免重复开启关闭协程的额外开销。skynet.fork 创建的协程是通过lua协程来实现的, 当一个协
2021-04-21 23:18:21
366
原创 排序与KMP
几种排序算法的复杂度希尔排序int shell_sort(int *data, int length) { if (!data || lenth <= 1) { return 0 } int gap = 0; int i = 0, j = 0; int temp; for (gap = length / 2;gap >= 1; gap /= 2) { for (i = gap;i < length;i ++) { temp = data[i];
2021-04-21 22:18:01
163
原创 遇到的问题,更新了skynet版本后, 运行包含protocol协议的lua文件时报错
报错内容:如上图所示,error loading module ‘protobuf.c’ from file ‘./luaclib/protobuf.so’原因:新版的skynet支持了lua5.4.2, lua版本不一致造成的解决方法:https://www.lua.org/ftp/到这个网站下载lua5.4.2的安装包重新装上lua5.4.2tar zxf lua-5.4.2.tar.gzcd lua-5.4.2make linux testmake installlua查看.
2021-04-21 17:21:50
887
原创 skynet服务别名 api
运行skynet服务器在skynet目录下./skynet example/config 运行的是config文本中 start字段的lua脚本环境变量 指的就是 这个config文本可以通过skynet.getenv(varName) 来获取环境变量skynet.setenv(varName, varValue) 慎用,因为会修改文本的内容skynet.init 是在 skynet.start执行之前执行skynet.start 服务初始化,参数是一个函数服务类型创建一个服务实例,
2021-04-21 15:23:39
281
原创 递归复杂度分析、归并排序、小和问题
今天学习了,递归的时间复杂度的估算方法,对数器和归并排序#include&amp;lt;iostream&amp;gt;#include&amp;lt;ctime&amp;gt;#include&amp;lt;cmath&amp;gt;using namespace std;void Myswap(int arr1, int arr2);void MySort(int arr[], int
2018-08-30 23:27:36
58
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人