go解决c10k problem(二)–db版下单场景

TL;DR 前言 这是一篇去年8月写的文章,本来是希望达到10k, 不过实际测试并没有成功,最终达到了1000+的事务,完成C10K的一个K,还有9个 :( DB选择 DB 类型 业务 io Mysql sql,支持事务,有缓存 强sql,强类型,类似java B & B+ Postgres sql,支持事务 Mongo nosql,key-value DB,读很快 弱sql,非强制,类似js B+ Redis nosql just kv,代码复杂 sqlite3 sql 强sql,支持事务 Btree 初步结论,理论上是随便用,先用sqlite3把,如果性能达不到,再来排查原因和更改DB 业务场景 我们设计一个sticker网站,可以售卖sticker,用户可以购买sticker,sticker是有库存的,如果用户的余额足够,则可以售卖,另外售卖的过程中,如果库存没了的话,需要回滚订单。 主要对象 用户 商品,库存字段也在商品身上 订单 主要流程 商品的详情页面,get v1/api/sticker/:id 商品的点赞+1接口,post v1/api/sticker/likes 下单接口,post v1/api/order 订单查看接口,get v1/api/order/:id 表现 get 接口 读 load PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 10154 ubuntu 20 0 1757000 36888 10020 R 362.
Read more →

go解决c10k problem(一)

零:缘起 最近两个事情 一个是easeprobe,haocl 对其http probe 做了一个10k的benchmark easeprobe benchmark 一个是读到go memory这篇文章 go-memory-ballast 谈到技术,并发是一个绕不过的话题,从第一家公司单机2万qps,到一个50w+ tps的超大型分布式交易系统。 那么自己能否来简单来测试一下呢? 跑一个web server,来个10k 并发,再来个可观测,看下瓶颈到底在哪里? 如何提升? 说干就干。 一:go http server goroutine的存在,让go在网络编程这块很高效,也有很多优秀的http 框架,比如 gin echo fasthttp fasthttp 比较快,我们先不读取db和其他,仅让cpu是一个瓶颈,仅写个hello world,收到请求后,返回一行文本。 示例代码 package main import ( "fmt" "github.com/valyala/fasthttp" ) // request handler in fasthttp style, i.e. just plain function. func fastHTTPHandler(ctx *fasthttp.RequestCtx) { fmt.Fprintf(ctx, "Hi there! RequestURI is %q", ctx.RequestURI()) } func main() { fasthttp.ListenAndServe(":8087", fastHTTPHandler) } 二:go http client 压测的client 2.
Read more →

学习web3的第三天-感受ether的心跳

学习web3的第三天 前两天主要学习了solidity的语言语法,以及合约的知识,并且部署到一个测试环境。 今天呢,我们来操作线上的环境:),哈哈哈,不是真正的写,仅仅读取一些线上的交易消息,感受下ether的律动。 预备 1 申请一个infura的账号 直接官网申请即可,他是一个web2的服务,提供的api服务,把ether的信息转换成一个api和消息投递出来。你也可以本地启动一个ether的node,来接入node也可以。 infura 主要作用:提供一个proxy,把ether的信息转换成一个api和消息投递出来。 这里需要注册一个账户,并且拿到一个project-id,有足够的的免费额度,供你使用 2 打开etherscan,来进行一个信息的比对和查询,确保后续测试正常 etherscan 3 打开vscode,准备写代码 do by yourself 读ether和监听ether的交易消息 1 先来读取一个ether的最高交易区块 // 获取最高交易区块,使用infura的api client, err := rpc.Dial("https://mainnet.infura.io/v3/<YOUR-PROJECT-ID>") if err != nil { log.Fatalf("Could not connect to Infura: %v", err) } var lastBlock Block err = client.Call(&lastBlock, "eth_getBlockByNumber", "latest", true) if err != nil { fmt.Println("Cannot get the latest block:", err) return } // 获取最高区块的高度 fmt.Printf("Latest block: %v\n", lastBlock.Number) 2 监听NewBlock事件 // 获取最高交易区块,使用infura的websocket ws, err := ethclient.
Read more →

学习web3的第二天

学习web3的第二天 今天就学习下写以太坊合约,并且部署到以太坊网络上,再创建一个读合约的go版本的api server。 使用到的技术如下 go ethereum solidity ganache-cli 预备:软件安装 1 安装golang brew install golang 2 安装ethereum follow official site geth 主要作用,提供一些命令行,如 apigen ,生成合约的go代码 3 安装solidity follow official site soliditylang 主要作用,提供solidity 的命令行,如 solc 4 安装ganache-cli brew install ganache-cli 主要作用,提供一个本地的节点,用来测试合约的功能 写合约主要源代码-solidity 代码 1 写合约的solidity代码 // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; contract MySmartContract { function Hello() public view returns (string memory) { return "Hello World"; } function Greet(string memory str) public view returns (string memory) { return str; } } 解释:首先是一个无参数的方法,Hello,一个是有参数的方法,Greet。
Read more →

学习web3的第一天

学习web3的第一天 闲着无事,虽然自己对web3热情满满,但实际并没有去参与,仅仅是买点币作为一个对行业的贡献。 前几天看到一个twitter话题,说一周学会web3开发,来吧,说干就干,开始学习。 此篇文章仅做记录使用,记录自己的收获和学习过程。 学习过程 1 打开google docs,看了下描述 一周学会 Web 3 开发 - 建议收集 从中发觉到几个网站,开始进行遍历和递归查找。 solidity极简入门 web3-from-zero 2 先遍历solidity极简入门 看了solidity的变量、函数、类等概念,在remix操作一番,结束,结果发现了一个uint256,这个感觉是从go中来的,翻看起来go-ethereum的代码,发现了一个uint256类型。 发现新的点 uint256 uint256 go-ethereum go-ethereum 3 uint256 类型 一看这个就是大数,go中最大是uint64, 256的话,就是四个uint64,是一个slice。打开uint256的github,一看才100多个star,这个是一个经典的类型,可以看出实际没有人关心这个类型,只关心它的操作。没有业务上的意义,不好展开。 github首页重点讲了他和标准库的对比,就是比标准库的bigint 强悍多少多少。自己没跑过benchmark,怀着好奇,用github的codespace打开一个实例,然后跑了下benchmark,哇,比bigint快好多。 4 go-ethereum 的依赖库分析 本来是去找下uint256在go-ethereum中的依赖和使用的,意外打开了go.mod,所以顺藤摸瓜的看了看go-ethereum的依赖库,发现了很多有名的go library。 首先是依赖的云服务,可以看出是aws和azure,cloudflare 具体要看怎么用的 azure-storage-blob-go azure-storage-blob-go aws-sdk-go aws-sdk-go cloudflare-go cloudflare-go docker docker 数据结构,用到了lru hashicorp/golang-lru golang-lru fastcache fastcache golang-set golang-set mmap mmap stack go-stack uint256 uint256 bloomfilter bloomfilter 数据传输 protobuf protobuf websocket websocket id生成器 google/uuid uuid 数据库
Read more →

go面试算法系列记录

面试 最近从阿里离职,开始准备面试,刷了一个月左右的leetcode,然后实践出真知,去面试了几家公司。 shopee 算法一面 螺旋矩阵,反向螺旋矩阵 描述要求 给定一个n x n的,打印出一个螺旋矩阵,比如: 输入n= 3, 输出,则打印 9 8 7 2 1 6 3 4 5 思路和解决 其实考察的是对数组的理解,还有矩阵的理解,就是找到矩阵的上下左右边界,遍历即可。反向的话,无非是从高到低遍历,正向的话,是从低到高遍历。 代码 func main() { matrix := generateMatrix(3) printMatrix(matrix) } func printMatrix(matrix [][]int) { if matrix == nil || len(matrix) == 0 { return } n := len(matrix) for i := 0; i < n; i++ { for j := 0; j < n; j++ { fmt.Printf("%d ", matrix[i][j]) } fmt.
Read more →

Go slice的一个坑

问题 最近在刷leedcode,求二叉树的路径和,给定一个二叉树,求所有符合条件的路径。原题见 113. Path Sum II 这道题需要遍历所有的节点,并且记录遍历路径上的节点,可以使用回溯法,深度优先的方法。 不过最近用习惯了广度优先的方法,把二叉树变成一个有序的队列,这种思想很好玩,把多个选择的,需要遍历的变成一个有序的来进行遍历即可,就是一个万能模板。 下面贴下代码 var result [][]int var ch = make(chan *TreeNode, 100) var sumChan = make(chan int, 100) var nodes = make(chan []int, 100) for len(ch) > 0 { for i := 0; i < len(ch); i++ { //获取当前节点 cur := <-ch //获取父节点的总和 parentSum := <-sumChan //获取父节点的所有路径节点序列 parents := <-nodes //当前节点的总和 curSum := parentSum + cur.Val //当前节点的序列 curNodes := append(parents, cur.Val) if cur.Left == nil && cur.
Read more →