Go - 是面向对象语言吗?
前言这篇文章代表博主正式开始学习和使用Go,以前的工作中主要使用一门动态的、解释型和面向对象的脚步语言。是的,你没猜错!它是 PHP。
Go 是一门编译静态语言,令人疑惑的它究竟是不是面向对象设计的。所以本文就以 OOP 的三大特性进行两门语言的对比,看看 Go 是不是面向对象的。
正文受 C 家族语言如PHP、Java等影响,得到一个不成文的结论:没有类(class)设计存在的就不是面向对象语言。
其中这是不对的,面向对象是一种编程思想,而非一种语言特有的技能。例如javascript 也能通过原型的方式实现面向对象编程,那它该如何归宿呢?
从严格意义上来说,Go 不是一门面向对象的编程语言。 但是并不妨碍这门语言大放异彩,如 k8s、docker、微服务、网关等。
本文的宗旨在于分析按常规OOP的特性下,GO 是否支持或者怎么实现面向对象特性。
类对象是一个由信息及对信息进行处理的描述所组成的整体,是对现实世界的抽象。它是类的实例。
而在 OOP 开发中,有超过90%的代码是写到一个个类中。类定义了一件事物的抽象特点。类的定义包含了数据的形式以及对数据的操作。
一个类的定义中常常包 ...
查看进程内存占用的正确姿势
前言在使用虚拟机跑PHP脚本,惊讶发现 top 命令看到的进程使用的内存总和竟然大于虚拟机可使用的最大物理内存。其实是分析的方向有些小问题,是因为通常大多数人关注的是 RSS 内存。
通常在 Linux 操作系统中对内存有着 VSS、RSS、PSS、USS等分类。不管你是用上面提到的 top、还是 ps aux 、或者查看 /proc/process_num(进程号)/status | grep RSS,往往大家下意识观察的都是 RSS。
往往这也是不太对的…
分类上面提到在 Linux 中有着VSS、RSS、PSS、USS等指标,通常情况下它们有着占用大小 VSS >= RSS >= PSS >= USS 的规律。先看下图:
VSS - Virtual Set Size 虚拟耗用内存
对应上图 - 区域1。
通常不用于判断进程占用的内存大小,因为它不仅包含共享库占用的全部内存,而且包含分配但未使用内存。
对于不了解虚拟内存的同学可以先看看博文《Linux - 内存管理》,了解操作系统是怎么做内存管理的。
RSS - Resident Set Size 实际使用 ...
Linux - 内存管理
【1】前言内存管理是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。
内存管理是操作系统很重要的一部分。作为一个后端开发来说,了解操作系统是如何进行内存管理是必须要的。
【2】读前须知在看正文之前,我们需要先了解一些相关的知识点帮助接下来的理解。
内存和外存内存(RAM ) 可以大致理解为在市面上看到的内存条,通常有4G、16G等容量。有着易失性、容量较小、价格偏贵读写很快得特点。这里需要和 CPU 的一二三级缓存分开理解哦。
外存 就大家所知的磁盘、硬盘等外存设备。有着容量大、价格便宜、随机读写较慢、顺序写速度接近内存、可持久化保持数据等特点。
物理内存物理内存其实就是内存,但是不是内存的容量大小操作系统都能使用到。比如 32 位的操作系统寻找空间理论上最大只有4G, 除去系统所占可能能使用的只有3.75G。所以不要闹出在 32 位操作系统上使用大于 4G的笑话哦,不过钱多当我没说。
其对应的空间地址称之为:物理内存地址(Physical Memory Address)。
虚拟内存实际上我们写的程序是没有直接 ...
Kafka -入门
Kafka 是什么近几年大数据炙手可热,相信大多数开发者多多少少了解或使用过 Kafka。博主也是刚入门的萌新,所以整理学习中的经验总结。授予有缘人。
Kafka 是什么?它是一款开源的消息引擎系统,是 Apache 基金会的一个顶级开源项目。由 Scala 和 Java 编写, 可惜我都不会。
对于刚接触 消息引擎系统(Messaging System) 这个词来说是有些迷茫的,维基百科中是这样描述:是为处理实时数据提供一个统一、高吞吐、低延迟的平台。其持久化层本质上是一个“按照分布式事务日志架构的大规模发布/订阅消息队列”。
简单的理解 Kafka 是在各个系统之间传输消息,从而实现松耦合的异步式数据传递。这时候可能有部分看官会想到一些如 XML、json、Protocol Buffer 等成熟方案,但 Kafka 使用的是纯二进制的字节序列传输信息。所以这也是 Kafka 的优势之一。
现在了解 Kafka 大致什么,那接下来开始使用起来吧。但在使用之前,需要选择一个合适的 Kafka 方案。是的,Kafka 有好几种。
Kafka 怎么选类似 Linux 有 RedHat、Ce ...
skiplist - 跳表
前言跳表(skiplist、跳跃表) 是一个很优秀的数据结构,比如用于 Redis、levelDB等出名的开源项目上。跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。
它的结构特点在名称能很好的体现出来,就像兔子一样,蹦蹦跳跳。可以结合下面的图有个初步的印象。
是不是看起来很形象了,接下来看看 Redis 是怎么实现跳表。
源码解读 本文讲解的版本为 Redis 6.0 ,可以在 server.h 头文件中找到对 skiplist 结构的定义。在 Redis 中,目前使用到跳表的只有 有序集合(zset)。
定义结构体处有段注释,也指明了跳表在 Redis 中的使用范围了。
ZSETs use a specialized version of Skiplists
// 有序集合的结构体
typedef struct zset {
dict *dict; // 哈希表是一种实现方式。
zskiplist *zsl; // 本文主题 跳表 实现方式。
} zset;
// 跳表结构体
typedef str ...
zipmap-压缩字典
前言hash 数据类型是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。每个 hash 可以存储 232 - 1 键值对(40多亿)。
redis 在 hash 类型数量比较小的时候会选择使用 zipmap 来实现存储。先看看 Redis 是怎么定义 zipmap的:
String -> String Map 数据结构优化了大小。 该文件实现了一个数据结构,将字符串映射到其他字符串,实现了一个 O(n) 查找数据结构,该结构设计为非常节省内存。 Redis Hash 类型将这种数据结构用于由少量元素组成的散列,一旦达到给定的元素数量就切换到散列表。 考虑到Redis Hashes多次用于表示由几个字段组成的对象,这在使用内存方面是一个非常大的胜利。
在 zipmap.c 文件的头部注释着这句话,从文中能提炼出几点信息:
使用字符串类型实现 ziplist 的基本布局,可以粗略描述为 “<key1><value1><key…><value…>“。
查询时候需要遍历 ...
quicklist-快速列表
前言这篇博文用来解读 Redis 数据类型 List 的一种实现。数据结构 quicklist。虽然 List 类型有多种实现,但 quicklist 是最常用的。
quicklist 是一个双向链表,但同时也是一个复合的结构体。结构中包括了另一种结构 ziplist。如果不熟悉这种结构体,请先阅读这篇博文:《ziplist - 压缩列表》。
文中介绍了 ziplist 是一种十分节省内存的结构,紧凑的内存布局、变长的编码方式在内存使用量上有着不小的优势。但是修改操作下并不能像一般的链表那么容易,需要从新分配新的内存,然后复制到新的空间。
所以结合了 ziplist 节省内存和双向链表优点的 quicklist 产生了。
源码解读quicklist在 quicklist.c 中可以找到名为 quicklist 的结构体:
typedef struct quicklist {
quicklistNode *head;
quicklistNode *tail;
unsigned long count;
unsigned l ...
intset - 整数数组
前言Set 是 Redis 数据类型的一种。集合中元素是唯一的,支持存储最大元素 2^64。因为是哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
但是 Set 除了哈希表之外,还有 intset 这种实现方式。 intset 是 Redis 独特设计的一种数据结构。当需要存储的数据全是正数且元素数量不大情况下,如 -2、-1、1、2… Redis 首选 intset 作为实现方式。
源码解读内存布局在 intset.h 中定义了 intset 的结构体:
typedef struct intset {
uint32_t encoding;
uint32_t length;
int8_t contents[];
} intset;
encoding 编码方式。目前共支持三种范围: INTSET_ENC_INT16:占用 2 个字节,存储范围为 -2^16 ~ 2^16-1。 INTSET_ENC_INT32:占用 4 个字节,存储范围为 -2^32 ~ 2^32-1。 INTSET_ENC_INT ...
ziplist - 压缩列表
前言相信对使用过 Redis 的人来说,数据类型 List 是不会陌生的吧。大多数人需要实现一个队列时候,首选的就是 List 了。但是其实 Redis 的 List 类型有多种实现方式。这篇文章就是介绍其中一种实现 ziplist - 压缩列表。
源码解读一如既往,关于 ziplist 的定义和实现还是放在一对文件中,分别是 ziplist.h 和 ziplist.c。在 ziplist.c 文件的头部有着这么一段注释介绍什么是 ziplist。
ziplist 是一个经过特殊编码的双向链表,旨在提高内存效率。 它存储字符串和整数值,其中整数被编码为实际整数而不是一系列字符。 它允许在 O(1) 时间内在列表的任一侧进行推送和弹出操作。 但是,由于每个操作都需要重新分配 ziplist 使用的内存,因此实际复杂性与 ziplist 使用的内存量有关。
从这段话得到:对于不同的数据类型有着不同的编码方式,理解为会对数据进行压缩,从而达到减少内存使用的目的。但是随着存储的 value 数据级增加,使用 ziplist 所付出的代价也随之增加。
ziplist 布局ziplist 是一 ...