- 博客(67)
- 资源 (1)
- 收藏
- 关注
原创 分布式链路追踪实战篇-日志库集成opentelemetry的思路
由上文可以知道分布式链路追踪的作用,但是距离应用到项目中,我们还需要对项目中一些关键组件进行opentelemetry的集成,例如日志库,ORM、http框架、rpc框架等。
2023-11-24 16:18:11
1280
2
原创 分布式链路追踪入门篇-基础原理与快速应用
链路追踪(Distributed Tracing)是一种用于监测和诊断分布式应用程序中请求路径的技术。在分布式系统中,单个请求可能会涉及多个服务和组件。链路追踪通过记录和分析请求在这些服务之间的传递路径和执行情况,帮助开发人员和运维团队理解系统的运行状况、性能和问题。Span(片段): 在链路追踪中,Span 是描述单个操作或事件的基本单元。一个请求被分解成一个或多个 Span,每个 Span 表示一个操作的开始和结束。例如,一个数据库查询、一个 HTTP 请求、一个函数调用等都可以作为一个 Span。
2023-11-23 11:58:30
1035
原创 Redis数据结构——跳跃表
0、简介zset的编码有压缩链表和跳跃表两种。除了当zset保存的元素少于128个或保存的所有元素大小都小于64字节时使用压缩链表,其余情况都是使用跳跃表跳跃表,又称跳表是Redis提供的有序集合(zset)类型主要的底层的数据结构。typedef struct zset { dict *dict; zskiplist *zsl; //跳跃表结构:zskiplist} zset;1、什么是跳跃表?跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指
2021-09-27 17:22:55
606
原创 详解Redis数据结构——字典
字典,又称映射(map),是一种保存键值对的抽象数据结构。这种数据结构是内置在很多高级语言中,但是Redis所使用的C语言并没有内置这种数据结构,因为Redis构建了自己的字典实现。Redis数据库就是使用字典来作为底层实现的,对数据库的增。删、差、改操作也是构建在对字典的操作之上的。一、字典的实现Redis的字典是使用哈希表作为底层实现的,一个哈希表里可以有多个哈希表节点,而每个哈希表节点就保存了字典中的一个键值对。1、哈希表typedef struct dictht { //哈希..
2021-09-26 17:32:46
956
原创 Redis之简单动态字符串SDS
前一段时间看了《Redis设计与实现》终于了解了Redis底层数据结构的实现原理,最近空闲想自己总结一遍记录下来我们都知道redis是由C语言编写的键值对数据库,所以我们很容易就会猜想redis最常用数据结构之一字符串就是C语言中传统的字符串类型,但实际上在redis中,C字符串只会在用在字面量时被使用,其余大多数情况下,redis是使用了自己构建的一个名为简单动态字符串(SDS)的类型。1、SDS的定义struct sdshdr { //记录buf数组中已使用字节的数量,即SDS所保.
2021-09-25 18:08:23
124
原创 golang下载自定义excel模板
主要是使用第三方的tealeg/xlsx包来生成excel文件package mainimport ( "bytes" "fmt" "github.com/gin-gonic/gin" "github.com/tealeg/xlsx" "net/http")type RowData struct { UserName string Age int StuId int}func FileDownload(c *gin.Context) { file := xlsx.NewF
2021-04-21 14:34:36
556
原创 Go的内存分配(一)
本文仅自己阅读笔记,详细请阅读原文draveness-内存分配器一、概述程序中的数据和变量都会被分配到程序所在的虚拟内存中,内存空间包含两个重要区域:栈区(Stack)和堆区(Heap)。不同的编程语言会选择不同的方式管理内存,而在Go语言中管理方式如下:栈区由编译器管理:其中函数调用的参数、返回值以及局部变量大都会被分配到栈上,这部分内存会由编译器进行管理;堆中的对象由内存分配器分配并由垃圾收集器回收。二、内存分配器内存管理一般包含三个不同的组件:用户程序、分配器和收集器,而当用户程序申
2021-03-11 23:58:56
763
1
原创 MySQL索引之B-树与B+树
我们知道MySQL中索引最常用的数据结构就是Hash和B+Tree,而其中的B+树更是大多数 MySQL 存储引擎的默认索引类型。那究竟什么是B+树?什么又是B树?它们之间有什么关系吗?B树/B-树1、哈希表、二叉查找树、B树的比较要弄清楚B+树,就得先知道B-树(B-树就是B树),首先MySQL索引之所以要使用树作为数据结构进行存储是因为它查询效率高,且可以保持有序,解决hash结构无序只能用作等值查询场景的缺陷。那为什么不使用二叉查找树?我们知道二叉查找树的查找插入的时间复.
2021-03-10 16:09:49
468
原创 Redis持久化之AOF日志
一、Redis为什么要实现持久化我们知道使用Redis,读写数据的速度都很快是因为数据存储在内存中,但是正是因为数据存储在内存中,所以我们无可避免要面对一个问题:一旦服务器宕机,内存中的数据将会全部丢失。二、Redis如何实现数据的持久化——AOF日志当我们把Redis用作缓存的时候,服务器宕机了,我们还可以从后端数据库恢复数据,但是当我们把Redis直接用作数据库的时候,我们就没办法通过后端数据库恢复了,所以此时我们就需要通过另外的方式来实现数据的持久化。1、如何用AOF日志实现数据持久化
2021-03-07 23:10:41
445
原创 Golang的内存逃逸分析
1、什么是逃逸分析?逃逸分析是一种确定指针动态范围的方法,可以分析在程序的哪些地方可以访问到指针。逃逸分析做了什么?Go是通过在编译期间通过编译器来进行逃逸分析,决定一个变量是放堆上还是栈上。其规则如下:变量没有...
2021-03-05 21:49:11
533
原创 分组位运算-数组中数字出现的次数(Go语言)
题目剑指offer56-I解题思路预备知识:异或运算 和 &运算1、异或运算:因为 1^1=0 1^0=0 所以 4^4 = 100 ^ 100 = 000 即 a ^ a = 0所以如果一组只有一个数出现一次的时候全员异或一遍即可得到这个特殊的数 eg:[3,1,3] = 3 ^ 1 ^ 3 = 12、&运算1&1=1 1&0=0 0&0=0 所以 6 & 1 = 110 & 001 = 000 或 6 & 4 = 1
2021-03-05 15:22:26
299
原创 为什么同一条sql有时候执行会变慢?
一、预备知识WALInnoDB在处理更新语句的时候是会遵循WAL(Write-Ahead Logging)机制的,即是更新了内存和做了写redo log这个磁盘操作而不是直接更新磁盘中对应的表(因为去到磁盘中全表遍历找到对应的表更新,因为这样会耗费很多时间),理想情况下是等到系统空闲时再把内存与磁盘中不一致的数据同步到磁盘。脏页&&干净页在MySQL中将数据从磁盘读取到内存是按页读取的,这个页称为数据页。当更新时WAL机制造成内存数据页和磁盘数据页内容不一致的页称为脏页。相反的
2021-03-04 22:46:31
2612
3
原创 golang的Redis客户端-Redigo
1、使用go get 下载redigo相关的包先下载redigo相关的包:go get github.com/garyburd/redigo/redis2、实践demo然后通过func Dial(network, address string, options ...DialOption) (Conn, error)可以连接到redis服务端,以下是个人写的一个小demo:package mainimport ( "fmt" "github.com/garyburd/redigo/red
2021-03-04 18:42:17
427
1
原创 Redis支持哪些数据类型?
Redis 数据类型Redis支持的数据类型主要有五种:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。1、String(字符串)string是redis最基本的类型,一个key对应一个value。string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。string类型是Redis最基本的数据类型,一个键最大能存储512MB。2、Hash(哈希)hash
2021-03-04 16:26:10
9508
2
原创 InnoDB的索引模型
在 MySQL 中,索引是在存储引擎层实现的,存储引擎没有统一的索引标准,所以在不同存储引擎中索引的工作方式并不一样。即使多个存储引擎支持同一种类型的索引,其底层的实现也可能不同。而在MySQL 数据库中,InnoDB 存储引擎的使用最为广泛,所以我们来了解一下InnoDB 的索引模型。1、InnoDB的索引模型InnoDB 使用了B+树索引模型,数据都是存储在 B+ 树中的。每一个索引在 InnoDB中是对应一棵B+树。例如我们建一个表,并插入一些数据。建表语句如下:create tab.
2021-02-25 21:40:12
136
原创 MySQL日志之redo log与binlog
在做SQL数据更新的时候,往往会设计两个重要的日志模块-redo log以及binlog1、redo logredo log是InnoDB引擎上特有的日志。①为什么需要redo log?因为在MySQL中,如果每次更新都立刻写进磁盘,磁盘是需要去到更新对应的表找到对应的记录进行修改。这个过程中的IO操作和查找操作都需要比较长的时间,这在更新操作频繁的系统里显然是效率低下的。所以为了解决这个问题,MySQL设计者使用了WAL 技术(Write-Ahead Logging)来解决这个问题,.
2021-02-25 16:04:41
160
原创 计算机硬件介绍之CPU与多线程
一、CPU1、、CPU的介绍CPU 是计算机的核心。它主要和内存进行交互,从内存中提取指令并执行它。一个 CPU 的执行周期是从内存中提取第一条指令、解码并决定它的类型和操作数,执行,然后再提取、解码执行后续的指令。重复该循环直到程序运行完毕。2、每个 CPU 都有一组特定的指令集每个 CPU 都有一组特定的指令集,特定的指令集只能自己执行。所以,x86 的 CPU 不能执行 ARM 的程序并且 ARM 的 CPU 也不能执行 x86 的程序。3、寄存器由于访问内存获取执行或数据要比执
2021-02-21 14:50:28
2207
原创 图解反转链表II-leetCode92(Go语言)
反转链表II题目关键点其实反转链表II相对于反转链表(leetcode-206)来说关键就是记录一些关键的结点:pre结点(m-n部分反转后的链表头结点的前置结点,即是m-1位置的那个结点)tail结点(m-n部分反转后的链表的尾结点,即是m位置的那个结点)图解流程下图为示例的详细过程代码(Go语言)type ListNode struct { Val int Next *ListNode}func reverseBetween(head *ListNode, m int
2021-02-06 15:46:33
292
原创 动态规划的详细思路-leetcode198打家劫舍(Go语言)
我们先来通过枚举找寻思路:eg:例如沿街房屋的金额如该数组:[5,8,2,3,1,7]我们知道前1个房间的可偷取的最大金额为5也可以简单看出前2个房间的可偷取的最大金额为max(5,8) = 8然后到了前3个房间我们就需要思考是否选择偷取第3个房间的金额,所以有以下选择:(1)不偷取第3个房间:那么前3个房间的可偷取最大金额为8(2)偷取第3个房间:那么则不可以偷取第二个房间的金额,所以最大金额相当于前1 (3-2) 个房间的最大金额+第3个房间的最大金额然后比较上面两种选择最大金额哪个更.
2021-02-04 15:46:13
139
原创 栈的基础应用-LeetCode20有效的括号(Go语言)
题目题目:给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。示例 1:输入:s = “()”输出:true示例 2:输入:s = “()[]{}”输出:true示例 3:输入:s = “([)]”输出:false示例 4:输入:s = “{[]}”输出:true思路(流程图):遍历字符串,遇到左方向的括号就把字符push入
2021-02-02 16:15:58
128
原创 二分查找法(Go语言)
二分查找法,在一个有序的数列里,把中间元素v与查找元素target相比较:若相等则返回若大于target则在v的右端继续使用二分查找法若小于target则在v的左端继续使用二分查找法二分查找法-迭代法(Go语言)package mainimport "fmt"//二分查找(前提必须在有序的数组里,查找target)//如果找到target,返回相应的索引index//如果没有找到target,返回-1//时间复杂度O(logN)func binarySearch(arr.
2021-02-01 17:39:08
2226
原创 数据结构-树与树几种特殊类型的基本了解
树与二叉树的简单介绍1、树的定义树是n个结点的有限集。n=0时称为空树。在任意一棵非空树中有如下特点有且只有一个称为根(root)的特定结点当n>1时,其余结点可分为m个互不相交的有限集T1,T2,…,Tm,其中每一个集合本身又是一棵树,并称为根的子树如下图:2、二叉树的定义二叉树是n(n>=0)个结点的有限集合,该集合或许为空集,或者由一个根结点和两个互不相交的、分别称为根结点的左子树和右子树的二叉树组成。(1)特殊二叉树-满二叉树在一棵二叉树中,如果所有分
2021-02-01 16:10:58
612
原创 基础排序算法-快速排序(Go语言)
快速排序的思想:其实就是把一个数组里的某位元素(本文是数组第一位)挪到正确的位置上,使得该元素左边全部小于它,右边元素全部大于它,这个过程也称为partition。然后再分别对左右两部分数组分别再进行partition,如此进行递归下去…直到左右两部分的子数组只含一个元素就结束递归。先来了解一下patition的过程:快速排序的详细过程(如下例):快速排序代码(Go语言):package mainimport "fmt"func quickSort(arr *[]int)
2021-01-30 13:34:23
294
原创 基础排序算法-归并排序(Go语言)
归并排序的思想其实就是对一个区间进行递归的分隔和合并,直到不可再分隔(即区间里只有一个元素):先递归分割为左右两个区间,然后对这两个区间进行合并。分隔:合并(箭头向上是合并过程①~③):其实最关键就是合并的过程例如将 【2,3,6,8】和【1,4,5,7】两部分合并,过程如下:归并排序代码(Go语言):package mainimport "fmt"func mergeSort(arr *[]int, l int, r int) { if l >= r {//不可再分.
2021-01-29 23:27:16
402
原创 基础排序算法-插入排序(Go语言)
插入排序其实和玩扑克牌时,拿到牌之后对牌整理顺序的思路是一样的,把后面比前面小的牌插入到前面去…插入排序代码(Go语言):package mainimport "fmt"func insertionSort(arr []int) []int { for i := 1; i < len(arr); i++ { for j := i; j >0; j--{ if arr[j] < arr[j-1] { temp := arr[j-1] arr[j-.
2021-01-29 21:34:52
84
原创 基础排序算法-选择排序(Go语言)
最近想重新系统的学习并总结一遍数据结构与算法,先从最基础的排序算法开始吧选择排序算法思路如下:代码实现(Go语言):package mainimport "fmt"func selectionSort(arr []int) []int{ for i:=0; i<len(arr); i++ { //1、遍历寻找[i,len(arr))区间里数组的最小值的下标minIndex minIndex := i for j:=i+1; j < len(arr); j++.
2021-01-29 20:56:45
161
原创 Linux的目录结构
我们进入终端的根目录,查看根目录下面的文件目录:其中/路径下一些重要的目录的解释如下:bin : bin是Binary的缩写, 这个目录存放着最经常使用的命令。dev : dev是Device(设备)的缩写, 该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。home : 存放用户的主目录。在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的mnt : 系统提供该目录给用户临时挂载别的文件系统。(例如我们将光驱挂载在/mnt
2021-01-24 21:16:05
86
原创 细说Golang的反射
一、什么是反射?Go 语言提供了一种机制在运行时更新变量和检查它们的值、调用它们的方法,但是在编译时并不知道这些变量的具体类型,这称为反射机制。二、为什么要用反射?以下是需要反射的 2 个常见场景:有时你需要编写一个函数,但是并不知道传给你的参数类型是什么,可能是没约定好;也可能是传入的类型很多,这些类型并不能统一表示。这时反射就会用的上了有时候需要根据某些条件决定调用哪个函数,比如根据用户的输入来决定。这时就需要对函数和函数的参数进行反射,在运行期间动态地执行函数。三、反射是如何实
2021-01-12 23:00:10
1477
原创 net/http源码分析之Go原生是如何搭建web程序
Go原生代码库实现一个简单的web程序以下实现了一个简单的web实例示例代码:package mainimport ( "fmt" "net/http")func handler(w http.ResponseWriter, r *http.Request) { //r.URL.Path是请求URL的路径部分 //其尾随的[1:]意思是“创建Path中第一个字符到结尾的子片段”(这将从路径名中删除前导“ /”)。 //将format字符串写入w fmt.Fpri
2021-01-07 20:15:44
279
原创 Go-select语句详解
1、什么是select语句?select 是 Go 中的一个控制结构。select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。2、select语句的作用?当我们需要同时从多个通道接收数据时,如果通道里没有数据将会发生阻塞。为了应对这种场景,Go内置了select关键字,可以同时响应多个通道的操作。3、select语句的语法结构select { case 表达式1: state
2021-01-06 16:05:43
1462
原创 Golang的init函数和main函数
一、init函数在Go中,init函数是用于包(package)的初始化。init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等每个包可以拥有多个init函数包的每个源文件也可以拥有多个init函数同一个包中多个init函数的执行顺序go语言没有明确的定义(说明)不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序init函数不能被其他函数调用,而是在main函数执行之前,自动被调用二、main函数像其他编程语言一样,main函数也是Go语言程序的默认入口
2021-01-06 14:23:24
1017
7
原创 Redis的安装、启动以及客户端连接
一、Redis的安装Mac OS X(使用Homebrew安装Redis)本人使用的是Mac OS X系统,在mac上很多软件都是使用homebrew来安装的,所以没有安装homebrew请自行安装然后在终端执行命令:brew install redis然后就会出现一下安装进度提示:==> Downloading https://download.redis.io/releases/redis-6.0.8.tar.gz##################################
2021-01-02 21:09:27
603
原创 为什么Redis会被广泛应用?
参考菜鸟教程以及慕课网的一站式学习Redis课程一、什么是Redis?Redis是一个key-value存储系统。是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。二、Redis的特性速度快支持数据持久化支持多种数据结构支持多种编程语言功能丰富简单主从复制高可用、分布式1、速度快Redis能读的速度是110000次/s,写的速度是81000次/s 。为什么速度快?答:主要是因
2021-01-02 16:00:24
382
原创 MySQL表的联结之inner join/outer join
一、关系表先看一个关系表的例子:假设有一个产品表:里面存储了产品描述、价格、供应商信息。然后表里有同一供应商生产的多种产品、那么在何处存储供应商信息?答:应新建一个表存储供应商信息,每个供应商占一行每个供应商具有唯一标识。此标识为主键。例如供应商ID而产品表只存储产品信息,它除了存储供应商ID作为外键以外不存储供应商的其他信息。主键:能唯一标识表中的每一行。外键:外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。二、联结表1、为什么要使用联结由上面关系表的例子我们
2020-12-30 17:21:36
764
原创 MySQL之GROUP BY分组
我们知道,在使用聚集函数都是表的所有数据或匹配特定的WHERE子句的数据上进行的。例如下面返回厂商id为1001生产了多少种产品的总数:但是当我们想知道所有厂商生产的产品的种类总数时、或者提供了数量超过100件的商品种类的总数时应该怎么处理?答:通过分组条件把数据分成多个分组,然后通过聚集函数对分别每个组进行计算一、创建分组分组是在SELECT语句中的GROUP BY子句中建立的。二、过滤分组MySQL允许我们用HAVING过滤分组,但注意这种过滤是基于完整分组而不是个别个体进行过滤。
2020-12-29 15:57:35
338
原创 MySQL之聚集函数
当我们只需要对表中数据进行汇总而不需要将它们实际检索出来的时候,我们可以使用MySQL提供的聚集函数。聚集函数:运行在行组上,计算和返回单个值的函数。AVG() :返回某列的平均值COUNT() : 返回某列的行数MAX() :返回某列的最大值MIN() :返回某列的最小值SUM() :返回某列值之和一、聚集函数1、AVG()2、COUNT()COUNT()可用于确定表中行的数目或符合特定条件的行的数目。它的两种使用方式:使用COUNT(*)对表中行的数目进行计数,不管表
2020-12-29 12:42:11
757
原创 MySQL之使用正则表达式进行搜索
一、什么是正则表达式正则表达式是用来匹配文本的字符集合。随着过滤条件复杂性的增加,使用匹配、比较和通配符等方式寻找数据已经不能满足要求。我们则使用正则表达式来匹配。例如:从一个文本文件中提取电话号码、在一个文本块找到所有重复的单词等。二、使用MySQL正则表达式MySQL用WHERE子句对正则表达式提供了初步的支持,允许指定正则表达式过滤select检索出的数据。(注:MySQL仅支持正则表达式里的一个子集)1、基本字符匹配这条语句与LIKE语句的模糊查询非常相似,它通过REGEXP告诉M
2020-12-27 15:08:42
166
原创 MySQL之使用通配符过滤
一、通配符通配符:用来匹配值的一部分的特殊字符。搜索模式:由字面值、通配或两者组合构成的搜索条件。LIKE操作符:为了在搜索子句中使用通配符,必须使用LIKE操作符。LIKE指示MySQL后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较1、百分号(%)通配符在搜索串中,%表示任意字符出现的任意次数。注意:%不仅能匹配一个到多个的字符,还能匹配0个字符。2、下划线(_)通配符在搜索串中,_能匹配任意字符,但是只能匹配单个字符。3、使用通配符的注意事项不要过度的使用通配符
2020-12-26 15:12:02
135
1
原创 Go协程间的通信
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、概念我们知道协程是独立执行的,他们之间没有通信。协程间必须通过通信协调/同步他们的工作。1、协程间通过通道(channel)来通信协程可以使用共享变量来通信,但是在Go中并不提倡这样做,因为这种方式给所有的共享内存的多线程都带来了困难。而Go是通过一种特殊的类型,通道(channel),一个可以用于发送类型化数据的管道,由其负责协程之间的通信,从而避开所有由共享内存导致的陷阱;这种通过通道进行通信的方式保证了同步
2020-12-24 20:42:41
3930
1
原创 Go协程
本文仅是自己阅读笔记,不正确之处请多包涵和纠正。原文The way to go一、什么是协程?1、进程和多线程一个应用程序是运行在机器上的一个进程;进程是一个运行在自己内存地址空间里的独立执行体。一个进程由一个或多个操作系统线程组成,这些线程其实是共享同一个内存地址空间的一起工作的执行体。几乎所有’正式’的程序都是多线程的,以便让用户或计算机不必等待,或者能够同时服务多个请求或增加性能和吞吐量。2、多线程的缺点因为在一个进程里的多个线程是共享内存的,意味着在多线程应用中内存中的数据是被多个
2020-12-24 14:25:31
441
2
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人