rocksdb原理
引擎整体架构
MemTable 与 WAL
RocksDB 使用 LSM (Log-structed Merge-tree)作为主要的存储数据结构,每当数据写入到 RocksDB 之中,就会被添加到 MemTable 内存的写缓冲区,以及一个磁盘上的超前写入日志(WAL)。数据会被写入到 WAL 和 MemTable,WAL 是 MemTable 的易失性保护机制。
RocksDB 中 Memtable 的数据结构有三种,分别是 skiplist、hash-skiplist、hash-linklist,跳表的好处在于插入的时候可以保证数据的有序,并且支持二分查找、范围查询。插入和搜索的代价都是 O(log n)。
在达到指定大小之后现有 MemTable 和 WAL 锁定变为不可变,新数据写入新的 MemTable 和 WAL。
SSTable
SSTable 是一种数据结构,当 MemTable 到达一定的上限之后,会 flush 到硬盘上 Sorted String Table (SSTable),并放置在第 0 层(L0),对应的 WAL 空间回收;L0 大小达到上限时,L0 ...
缓存一致性
缓存一致性
一、缓存常见问题
缓存与数据库数据一致性
缓存雪崩
缓存击穿
缓存穿透
二、缓存一致性问题
缓存一致性问题的产生主要是因为请求需要事务地处理缓存和数据库。但实际操作中,难以保证事务性。
操作隔离性:并发请求时,无法保证多个请求在处理缓存和处理数据库两个步骤上的时序。
操作原子性:即使单个请求,也无法保证处理缓存和处理数据库的原子性,可能存在某个操作失败的情况
2.1 缓存更新策略
根据缓存更新策略,可以分为以下三类
旁路缓存(cache aside)
写穿(write/read through)
异步写回(write behind / write back)
接下来根据不同的更新策略来分析产生一致性问题的原因和解决办法
2.2 旁路缓存(cache aside)
旁路缓存是开发中最常用的缓存使用策略,这个策略是以数据库中的数据为主,缓存只是按需从数据库中加载。该策略缓存中的数据只读,不作修改操作(当数据有修改,也仅仅删除缓存中的数据),因此也称只读模式
读写策略如下:
读策略:
读缓存,
缓存中存在数据,直接返回
缓存中不存在该数据,从数据库中查询
将查询到的 ...
nodejs简单使用
hello world
创建test.js文件,内容如下
12var hello = 'Hello world!';console.log(hello);
使用node进行运行
1node test.js
使用第三方包
以xlsx为例,介绍使用第三方包
在当前目录下安装xlsx,执行如下命令之后会在当前目录创建出node_modules文件夹,以及package.json和package-lock.json文件
1npm install xlsx
创建test.js文件
1234var xlsx = require('xlsx');let data = [{name: "John", city: "Seattle"}, {name: "Mike", city: "Los Angeles"}];let worksheet = xlsx.utils.json_to_sheet(data);console.log(&q ...
GMP原理
[TOC]
2.4 GMP源码剖析
2.4.1 协程G结构体
1234567891011121314151617181920212223242526// src/runtime/runtime2.gotype g struct { stack stack // 保存当前协程栈的上界和下界 // stackguard0 是对比 Go 栈增长的 prologue 的栈指针 // 如果 sp 寄存器比 stackguard0 小(由于栈往低地址方向增长),会触发栈拷贝和调度 // 通常情况下:stackguard0 = stack.lo + StackGuard,但被抢占时会变为 StackPreempt stackguard0 uintptr // offset known to liblink // stackguard1 是对比 C 栈增长的 prologue 的栈指针 // 当位于 g0 和 gsignal 栈上时,值为 stack.lo + StackGuard // 在其他栈上值为 ~0 用于触发 more ...
golang垃圾回收
golang三关
https://learnku.com/blog/Aceld/tags/three-passes-of-golang_67253
垃圾回收:
https://learnku.com/articles/68141
go协程调度
二、协程调度
2.1 线程和协程
2.1.1 线程调度开销
在操作系统中,线程是cpu调度的基本单位,然而,线程是由操作系统负责调度。线程切换时:
线程需要从用户态陷入内核态,栈指针指向内核态栈地址,同时保存上下文,如各种用户空间寄存器的数据(通用寄存器,段寄存器,标识寄存器等等)
操作系统调度算法找到需要调度的线程之后,又要从内核态切换回用户态,恢复上下文,栈指针指向新线程的用户态栈地址。
整个切换过程中,为了安全,需要引入更强的内核检查。
这些操作导致线程切换存在不小的开销
2.1.2 协程调度
既然线程切换要从用户态切换到内核态才能让操作系统进行调度,那么我们可以将其抽象的看作“用户态”线程和“内核态”线程,用户态线程1:1绑定在内核态线程上面完成CPU调度,为了降低陷入内核态的开销,我们可以创建多个用户态线程绑定到一个内核态线程上面,我们自己调度用户态线程,这样,用户态线程切换的时候就无需陷入内核了
于是,协程便应运而生,协程即是用户级线程,协程的切换无需操作系统参与,无需陷入内核态,只需用户在用户态实现协程的切换即可(切换栈指针,程序计数器,保存少数几个寄存器),切换开销 ...
go程序启动过程
[[toc]]
一、go启动流程
1.1 第一个go程序
首先,我们来看一个简单的go程序启动流程
123456789// main.goimport "fmt"func main() { str := make([]string, 0) str = append(str, "zhiminding") fmt.Printf("hello,%v", str)}
对上面的go程序进行编译,生成main
1go build -gcflags="-l -N" # -l 禁止内联, -N 禁止优化
查看编译出来的二进制和汇编代码
1go tool objdump -s "main.main" -S ./main # 用户实现的main函数,在源码中是main.main
该方法在控制台输出汇编代码,阅读和调试起来不方便,我们可以用lensm工具查看汇编代码
1.2 生产力工具lensm
为了方便看汇编和源代码,在go源码之间方便跳转,我们可以安装一个 ...
go语言数据结构
slice
123list := make([]int,0)list = append(list,1)list = append(list,1)
编译期:
1234567891011121314// cmd/compile/internal/types.NewSlicefunc NewSlice(elem *Type) *Type { if t := elem.Cache.slice; t != nil { if t.Elem() != elem { Fatalf("elem mismatch") } return t } t := New(TSLICE) t.Extra = Slice{Elem: elem} elem.Cache.slice = t return t}
底层数据结构
123456789101112// reflect.SliceHeadertype SliceHeader struct { Data uintptr Len int Cap in ...
对象存储使用
上传流程
文件上传分为客户端上传(主要是指网页端和移动端等面向终端用户的场景)和服务端上传两种场景,具体可以参考文档业务流程。
服务端SDK在上传方面主要提供两种功能,一种是生成客户端上传所需要的上传凭证,另外一种是直接上传文件到云端。
客户端上传凭证
客户端(移动端或者Web端)上传文件的时候,需要从客户自己的业务服务器获取上传凭证,而这些上传凭证是通过服务端的SDK来生成的,然后通过客户自己的业务API分发给客户端使用。根据上传的业务需求不同,七牛云 Go SDK支持丰富的上传凭证生成方式。
拷贝
// 存储相关功能的引入包只有这两个,后面不再赘述
import (
“github.com/qiniu/go-sdk/v7/auth/qbox”
“github.com/qiniu/go-sdk/v7/storage”
)
accessKey := “your access key”
secretKey := “your secret key”
mac := qbox.NewMac(accessKey, secretKey)
简单上传的凭证
最简单的上传凭证只需要AccessKey,S ...
vue nginx运行
注:这里开始认为各位都会使用nginx
打包vue项目
1npm run build
测试打包的项目是否可以运行
1serve dist
可以正常运行
编译报错请移步到:renren-fast-vue@1.2.2 项目编译报错: build gulp
部署vue项目到nginx
接下来将renren-fast-vue 项目生成的dist 目录修改为:renren-fast-vue 并压缩为:renren-fast-vue.zip
复制renren-fast-vue.zip 到服务器
解压到:/usr/local/nginx/
vue项目的nginx配置文件不直接在nginx.conf中进行配置,将配置保存在/usr/local/nginx/conf/vhost/renren-fast-vue.conf
配置内容为:vi /usr/local/nginx/conf/vhost/renren-fast-vue.conf
1234567891011121314151617181920212223server { listen 7000; se ...