缓冲区分析

Redis 中的客户端

依然范特西╮ 提交于 2020-03-12 22:24:27
Redis 是一个客户端服务端的程序,服务端提供数据存储等等服务,客户端连接服务端并通过向服务端发送命令,读取或写入数据,简单来说,客户端就是某种工具,我们通过它与 Redis 服务端进行通讯并完成数据操作。 客户端并不是 Redis 的核心,Redis 的核心是它的服务端程序,服务端程序才是完成数据存、取,持久化等等我们使用频繁的各种操作的执行者。但也不是说客户端就没什么作用,客户端在整个 Redis 服务体系中也是非常重要的一环。本篇先来看看 Redis 客户端的一些特性以及实现原理。 一、客户端的基本属性 redis 中为客户端抽象的数据结构是,server.h/client 结构,我这里是 redis-4.0.x 版本,不同版本或许稍有不同,每一个 redis 客户端成功的连接上服务端之后,服务端就会创建一个 client 结构实例,并以链表的形式链接所有连接成功的客户端。 这个结构最主要作用就是存储当前客户端的大量属性,套接字、名字、标志,状态等等信息,这些信息非常的重要,当服务端为客户端服务时,很多的信息例如当前要执行的命令、参数都会从这里获取。我们一个一个来了解。 1、客户端名称 默认情况下,所有连接成功的客户端都是没有名字的,这一点你可以通过向服务发送 client list 命令验证,它会返回当前服务端成功建立的客户端以及他们的基本信息。例如: 可以看到,name

进程的经典同步问题

时间秒杀一切 提交于 2020-03-12 19:07:17
P、V操作描述简单同步 设同步信号量empty,含义为缓冲单元为空,初值为1 设同步信号量full,含义为缓冲单元为满,初值为0 输入进程: 申请空缓冲单元; P(empty); 输入数据到缓冲单元; 输入数据到缓冲单元; 释放满缓冲单元; V(full) 计算进程 申请满缓冲单元; P(full) 从缓冲单元取数据; 从缓冲单元取数据 释放空缓冲单元; V(empty); 同步:每一个同步信号量P、V操作成对出现在不同的进程代码中 经典同步问题 生产者消费者问题 P、V操作描述进程同步互斥问题步骤: 分析进程同步互斥关系; 设响应同步互斥信号量; 用P、V操作描述进程活动。 描述了一组生产者向一组消费者提供产品(数据),它们共享一个有界缓冲区,生产者向其中投放产品,消费者从中取出产品消费,生产者和消费者互斥使用整个缓冲池。 分析: 只要缓冲区未满,生产者就可把产品送入缓冲区,只要缓冲区未空,消费者便可从缓冲区取走产品并消耗它。 仅当缓冲区满时,生产者被阻塞,类似地,缓冲区空时,消费者被阻塞。 设置两个同步信号量:empty:表示空缓冲单元的数目,初值为缓冲区的大小n; full:表示满缓冲单元(即产品)的数目,初值为0; 设置互斥信号量mutex:表示整个缓冲池,初值为1。 生产者进程Pi(i=1,2,……,m) 总结 两个P操作不可用颠倒,如生产者进程中如颠倒

TCP通信粘包问题分析和解决

自古美人都是妖i 提交于 2020-03-02 19:48:32
TCP通信粘包问题分析和解决(全) 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的。因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 对于UDP,不会使用块的合并优化算法,这样,实际上目前认为,是由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。所以UDP不会出现粘包问题。 ==================================================================== 在介绍TCP之前先普及下两个相关的概念,长连接和短连接。 1.长连接 Client方与Server方先建立通讯连接,连接建立后 不断开, 然后再进行报文发送和接收。 2.短连接 Client方与Server每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。此种方式常用于一点对多点通讯,比如多个Client连接一个Server.

【Kafka】深入探究--为什么Kafka速度快

痴心易碎 提交于 2020-02-25 19:22:23
Kafka的消息是保存或缓存在磁盘上的,一般认为在磁盘上读写数据是会降低性能的,因为寻址会比较消耗时间,但是实际上,Kafka的特性之一就是高吞吐率。 即使是普通的服务器,Kafka也可以轻松支持每秒百万级的写入请求,超过了大部分的消息中间件,这种特性也使得Kafka在日志处理等海量数据场景广泛应用。 针对Kafka的基准测试可以参考, Apache Kafka基准测试:每秒写入2百万(在三台廉价机器上) 下面从数据写入和读取两方面分析,为什么Kafka速度这么快。 写入数据 Kafka会把收到的消息都写入到硬盘中,它绝对不会丢失数据。为了优化写入速度Kafka采用了两个技术, 顺序写入 和 MMFile 。 顺序写入 磁盘读写的快慢取决于你怎么使用它,也就是顺序读写或者随机读写。在顺序读写的情况下,某些优化场景磁盘的读写速度可以和内存持平(注:此处有疑问, 不推敲细节,参考 http://searene.me/2017/07/09/Why-is-Kafka-so-fast/ )。 因为硬盘是机械结构,每次读写都会寻址->写入,其中寻址是一个“机械动作”,它是最耗时的。所以硬盘最讨厌随机I/O,最喜欢顺序I/O。为了提高读写硬盘的速度,Kafka就是使用顺序I/O。 而且Linux对于磁盘的读写优化也比较多,包括read-ahead和write-behind,磁盘缓存等

31.Linux-分析并制作环形缓冲区

给你一囗甜甜゛ 提交于 2020-02-22 23:43:29
1.环形缓冲区log_buf[]又是存在内核的哪个文件呢?   位于/proc/kmsg里,所以除了dmesg命令查看,也可以使用cat /proc/kmsg来查看 2.但是,dmesg命令和cat /proc/kmsg有所不同 2.1 dmesg命令   每次使用,都会打印出环形缓冲区的所有信息 2.2 cat /proc/kmsg   只会打印出每次新的环形缓冲区的信息   比如,第一次使用cat /proc/kmsg,会打印出内核启动的所有信息   第二次使用cat /proc/kmsg,就不会出现之前打印的信息,只打印继上次使用cat /proc/kmsg之后的新的信息,比如下图所示: 3.接下来我们便进入内核,找/proc/kmsg文件在哪生成的   搜索"kmsg",找到位于fs\proc\proc_misc.c 文件的proc_misc_init()函数中,   该函数主要用来生成登记的设备文件,具体代码如下所示: const struct file_operations proc_kmsg_operations = { . read = kmsg_read , //读函数 . poll = kmsg_poll , . open = kmsg_open , . release = kmsg_release , } ; void __init proc_misc

redis内存消耗详解

[亡魂溺海] 提交于 2020-02-14 22:43:06
Redis所有的数据都存在内存中,相对于廉价的硬盘,内存资源还是比较昂贵的,因此如何高效利用redis内存变得非常重要。 内存消耗分析 管理内存的原理和方法 内存优化技巧 一、内存消耗 理解redis内存,首先要掌握redis内存消耗在哪些方面。有些内存消耗是必不可少的,而有些可以通过参数调整和合理使用来规避内存浪费。 1.1 内存使用统计 首先需要了解redis自身使用内存的统计数据,可通过执行info memory命令来获取内存相关指标 used_memory redis分配器分配的内存总量,也就是内部存储的所有数据内存占用量 used_memory_human 以可读的格式返回used_memory used_memory_rss 从操作系统的角度显示redis进程占用的物理内存总量 used_memory_peak 内存使用的最大值,表示used_memory的峰值 used_memory_peak_human 以可读的格式返回used_memory_peak used_memory_lua Lua引擎所消耗的内存大小 mem_fragmentation_ratio used_memory_rss/used_memory比值。表示内存碎片率 mem_allocator redis 所使用的内存分配器,默认为jemalloc 需要重点关注的指标有:used_memory

内存泄漏 和 内存溢出

别来无恙 提交于 2020-02-11 03:45:59
在计算机科学中, 内存泄漏(memory leak) 指由于疏忽或错误造成程序 未能释放已经不再使用的内存 的情况。内存泄漏并非指内存在物理上的消失,而是 应用程序 分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏与许多其他问题有着相似的症状,并且通常情况下只能由那些可以获得程序源代码的程序员才可以分析出来。然而,有不少人习惯于把任何不需要的内存使用的增加描述为内存泄漏,严格意义上来说这是不准确的。    一般我们常说的内存泄漏 是指堆内存的泄漏 。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显式释放的内存。应用程序一般使用malloc,calloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。 内存溢出 就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。 比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。 这是程序语言中的一个概念,典型的,在C语言中,在分配数组时为其分配的长度是1024,但往其中装入超过1024个数据时,由于C语言不会对数组操作进行越界检查,就会造成内存溢出错误 在程序员设计的代码中包含的

浅谈MapReduce工作机制

被刻印的时光 ゝ 提交于 2020-02-03 03:52:15
1.MapTask工作机制   整个map阶段流程大体如上图所示。简单概述:input File通过getSplits被逻辑切分为多个split文件,通通过RecordReader(默认使用lineRecordReader)按行读取内容给map(用户自己实现的map方法),进行处理,数据被map处理结束之后交给OutputCollector收集器,对其结果key进行分区(默认使用hash分区),然后写入buffer,每个map task 都有一个内存缓冲区,存储着map的输出结果,当缓冲区快满的时候需要将缓冲区的数据以一个临时文件的方式存放到磁盘,当整个map task结束后再对磁盘中这个map task产生的所有临时文件做合并,生成最终的正式输出文件,然后等待reduce task来拉数据。 详细步骤: 1.首先, 读取数据组件 InputFormat (默认TextInputFormat)会通过 getSplits 方法对输入目录中文件进行 逻辑切片规划 得到splits,有多少个split就对应启动多少个MapTask。split与block的对应关系可能是一对多,默认是一对一。 2.将输入文件切分为splits之后,由 RecordReader 对象(默认LineRecordReader)进行读取,以"\n"作为分隔符,读取一行数据返回<key,value>

QTcpSocket 及 TCP粘包分析

試著忘記壹切 提交于 2020-02-02 03:53:10
~~~~我的生活,我的点点滴滴!! 这两天用Qt简单的实现一个tcp多线程client,在此记录下知识。 一、长连接与短连接 1、长连接 Client方与Server方先建立通讯连接,连接建立后不断开, 然后再进行报文发送和接收。 2、短连接 Client方与Server每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。此种方式常用于一点对多点通讯,比如多个Client 连接一个Server。 二、什么时候需要考虑粘包问题? 1、如果利用tcp每次发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样就不会出现粘包问题(因为只有一种包结构, 类似于http协议)。关闭连接主要要双方都发送close连接(参考tcp关闭协议)。如:A需要发送一段字符串给B,那么A与B建立连接,然后发 送双方都默认好的协议字符如"hello give me sth abour yourself",然后B收到报文后,就将缓冲区数据接收,然后关闭连接,这样粘包问题 不用考虑到,因为大家都知道是发送一段字符。 2、如果发送数据无结构,如文件传输,这样发送方只管发送,接收方只管接收存储就ok,也不用考虑粘包。 3、如果双方建立连接,需要在连接后一段时间内发送不同结构数据,如连接后,有好几种结构: a、"hello give me abour your message" b、"Don

BIO、NIO、AIO模型分析

耗尽温柔 提交于 2020-01-22 15:21:10
什么是 I/O 在计算机系统中I/O就是输入(Input)和输出(Output)的意思,针对不同的操作对象,可以划分为磁盘I/O模型,网络I/O模型,内存映射I/O, Direct I/O、数据库I/O等,常见的I/O有磁盘I/O和网络I/O。 什么是IO的Block呢?考虑下面两种情况: 用系统调用read从socket里读取一段数据 用系统调用read从一个磁盘文件读取一段数据到内存 对于第一种情况,算作Block,因为Linux无法知道网络上对方是否会发数据。如果没数据发过来,对于调用read的程序来说,就只能“等”。对于第二种情况,不算做Block。 一个解释是,所谓“Block”是指操作系统可以预见这个Block会发生才会主动Block。例如当读取TCP连接的数据时,如果发现Socket buffer里没有数据就可以确定定对方还没有发过来,于是Block;而对于普通磁盘文件的读写,也许磁盘运作期间会抖动,会短暂暂停,但是操作系统无法预见这种情况,只能视作不会Block,照样执行。我们讨论的BIO、NIO和AIO都是针对网络I/O模型。 进程中的IO调用步骤大致可以分为以下四步: 进程向操作系统请求数据 ; 操作系统把外部数据加载到内核的缓冲区中; 操作系统把内核的缓冲区拷贝到进程的缓冲区 ; 进程获得数据完成自己的功能 ; 当操作系统在把外部数据放到进程缓冲区的这段时间