文章目录

  • 摘要
  • 环境配置
    • 1. 远程服务器[可选择]
    • 2. 配置VSCode
    • 3. 设置go mod
  • 编程实现
    • 1. 导入boltdb
    • 2. 设置flag
    • 3. 创建HTTP API
    • 4. DB模块
    • 5. 更新API
    • 6. 测试
    • 7. web分离
    • 8. 更新main
  • 参考资料

摘要

本节要实现的有2点

  • 环境配置:远程服务器 + VS Code设置
  • 实现类似redis的set和get功能
    • 基于bolt.DB实现db模块
    • 实现简单的http web模块

环境配置

1. 远程服务器[可选择]

远程服务器比较稳定,当然也是多折腾体验。

腾讯云服务器购买详情&一些奇奇怪怪的软件设置,请参考: 详细的配置信息

2. 配置VSCode

安装 Remote SSH插件

连接服务器

切换第一个tab,打开资源管理器,添加目录

3. 设置go mod

查看go版本和配置

[root@VM-24-14-centos ~]# go version
go version go1.17 linux/amd64
[root@VM-24-14-centos ~]# echo $GOPATH
/data/go
[root@VM-24-14-centos ~]# echo $GOROOT
/usr/local/go

vscode安装tools

设置vscode go的选项

    "go.installDependenciesWhenBuilding": true,"go.useCodeSnippetsOnFunctionSuggestWithoutType": true,"go.autocompleteUnimportedPackages": true,"go.gotoSymbol.includeImports": true,"go.useCodeSnippetsOnFunctionSuggest": true,"go.inferGopath": true,

编程实现

1. 导入boltdb

[root@VM-24-14-centos go]# mkdir kv-demo
[root@VM-24-14-centos go]# cd kv-demo
[root@VM-24-14-centos kv-demo]# go mod init example.com/kv-demo
[root@VM-24-14-centos kv-demo]# go mod tidy
[root@VM-24-14-centos kv-demo]# go mod vendor
[root@VM-24-14-centos kv-demo]# go run main.go

2. 设置flag

目前就一个参数db-location,后续可以添加

// main.go
var (dbLocation = flag.String("db-location", "my.db", "The path to the database location")
)func main() {flag.Parse()db, err := bolt.Open(*dbLocation, 0600, nil)if err != nil {log.Fatal(err)}defer db.Close()
}

3. 创建HTTP API

先简单的mock http api

// main.go
http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Get Called")})http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Set called")
})log.Fatal(http.ListenAndServe(":8090", nil))
[root@VM-24-14-centos kv-demo]# curl http://127.0.0.1:8090/set
Set called
[root@VM-24-14-centos kv-demo]# curl http://127.0.0.1:8090/get
Get Called

4. DB模块

目前位置db的功能都在main里面,我们分离出单独的db模块

  • 创建DB
  • 设置key
  • 获取key
  • 创建默认Bucket
func NewDatabase(dbLocation string) (db *Database, closeFunc func() error, err error) {boltDb, err := bolt.Open(dbLocation, 0600, nil)if err != nil {return nil, nil, err}db = &Database{db: boltDb}closeFunc = boltDb.Closeif err := db.createDefaultBucket(); err != nil {return nil, nil, fmt.Errorf("create default bucket failed: %v", err)}return db, closeFunc, nil
}func (db *Database) SetKey(key string, value []byte) error {return db.db.Update(func(tx *bolt.Tx) error {b := tx.Bucket(defaultBucket)return b.Put([]byte(key), value)})
}func (db *Database) GetKey(key string) ([]byte, error) {var rc []byteerr := db.db.View(func(tx *bolt.Tx) error {b := tx.Bucket(defaultBucket)rc = b.Get([]byte(key))return nil})return rc, err
}func (db *Database) createDefaultBucket() error {return db.db.Update(func(tx *bolt.Tx) error {_, err := tx.CreateBucketIfNotExists([]byte(defaultBucket))return err})
}

5. 更新API

更新set & get http api来

 http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) {r.ParseForm()key := r.Form.Get("key")value, err := db.GetKey(key)fmt.Fprintf(w, "%q:%q; %v Get Called\n", key, value, err)})http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) {r.ParseForm()key := r.Form.Get("key")value := r.Form.Get("value")err := db.SetKey(key, []byte(value))fmt.Fprintf(w, "err: %v; Set called\n", err)})

6. 测试

  • Set a:b
  • Get a
[root@VM-24-14-centos src]# curl 'http://127.0.0.1:8090/set?value=b&key=a'
"a":"b"; <nil>; Set called
[root@VM-24-14-centos src]# curl http://127.0.0.1:8090/get?key=a
"a":"b"; <nil> Get Called

7. web分离

类似db分离,web也是单独的模块

  • 创建
  • 处理get
  • 处理set
type Server struct {db *db.Database
}func NewServer(db *db.Database) *Server {return &Server{db: db}
}func (s *Server) GetHandler(w http.ResponseWriter, r *http.Request) {r.ParseForm()key := r.Form.Get("key")value, err := s.db.GetKey(key)fmt.Fprintf(w, "%q:%q; %v Get Called\n", key, value, err)
}func (s *Server) SetHandler(w http.ResponseWriter, r *http.Request) {r.ParseForm()key := r.Form.Get("key")value := r.Form.Get("value")err := s.db.SetKey(key, []byte(value))fmt.Fprintf(w, "%q:%q; %v; Set called\n", key, value, err)
}

8. 更新main

web模块在main中调用

 svr := web.NewServer(db)http.HandleFunc("/get", svr.GetHandler)http.HandleFunc("/set", svr.SetHandler)log.Fatal(http.ListenAndServe(*httpAddress, nil))

参考资料

本节完整代码:https://github.com/YuriyNasretdinov/distribkv/tree/part1

youtube视频:https://www.youtube.com/watch?v=oPwGrCoOUdo&list=PLWwSgbaBp9XrMkjEhmTIC37WX2JfwZp7I&index=5&t=746s

B站视频:https://www.bilibili.com/video/BV1jY411L7SA/

怎么实现一个分布式kv系统 #1 local database相关推荐

  1. Spring Cloud 5分钟搭建教程(附上一个分布式日志系统项目作为参考) - 推荐

    http://blog.csdn.net/lc0817/article/details/53266212/ https://github.com/leoChaoGlut/log-sys 上面是我基于S ...

  2. Spring Cloud 5分钟搭建教程(附上一个分布式日志系统项目作为参考)

    Spring Cloud 5分钟搭建教程(附上一个分布式日志系统项目作为参考) 上面是我基于Spring Cloud ,Spring Boot 和 Docker 搭建的一个分布式日志系统. 目前已在我 ...

  3. 一个分布式***检测系统的研究与设计

    一个分布式 ***检测 系统的研究与设计 安  娜,吴晓南,陈晓江,房鼎益 (西北大学 计算机科学系,陕西 西安  710069) 摘要:针对目前***检测系统不能适应异构 网络环境.缺乏协同响应的不 ...

  4. 为自己搭建一个分布式 IM 系统二【从查找算法聊起】

    前言 最近这段时间确实有点忙,这篇的目录还是在飞机上敲出来了的. 言归正传,上周更新了 cim 第一版:为自己搭建一个分布式 IM(即时通讯) 系统:没想到反响热烈,最高时上了 GitHub Tren ...

  5. 手把手教你搭建一个基于Java的分布式爬虫系统

    http://blog.51cto.com/xpleaf/2093952 1 概述 在不用爬虫框架的情况,经过多方学习,尝试实现了一个分布式爬虫系统,并且可以将数据保存到不同地方,类似MySQL.HB ...

  6. 分布式追踪系统的对比、实现与使用—NodeTracing

    前言 现状 各类trace解决方案 各大厂商trace系统对比 NodeTracing概览 NodeTracing使用 下载 快速开始&单例启动 生产部署&集群启动 安装自动探针 探针 ...

  7. 小米开源分布式KV存储系统Pegasus 原创 2017-10-19 孙伟杰 InfoQ

    小米开源分布式KV存储系统Pegasus 原创  2017-10-19  孙伟杰  InfoQ 作者|孙伟杰编辑|小智小米近日开源了分布式 KV 存储系统 Pegasus,这个小米自造的轮子背后,有着 ...

  8. java kafka分布式_Kafka分布式消息系统

    1.简介 Kafka是一个分布式消息系统,使用Scala语言进行编写,具有高水平扩展以及高吞吐量特性. 目前流行的消息队列主要有三种:ActiveMQ.RabbitMQ.Kafka ActiveMQ. ...

  9. 基于SpringBoot和Vue的分布式爬虫系统(JavaWeb)

    前言 本期案例分享,学长给大家上点干货,手把手带你开发一个分布式爬虫系统.通过这个项目,你将学习到下面几点: 架构设计.如果设计一个通用的爬虫系统?一个系统支持爬取所有的网站. 分布式开发经验.分布式 ...

最新文章

  1. 学python多贵_老男孩学习Python多少钱,学习Python贵吗?
  2. 使用Orange Pi Zero做小小服务器(VNC篇)
  3. python开发的优秀界面-:Python做推荐系统,界面用什么实现
  4. Ethernet/IP 学习笔记四
  5. 采购订单建立增加客户数据增强示例
  6. c语言中预处理指令的作用,C语言中常用预处理指令
  7. 如何安装 jupyter lab 和 jupyter notebook?
  8. Vista 系统C盘(系统盘)越来越小的问题.与解决.
  9. jquery(ajax)+ashx简单开发框架(原创)
  10. python数据库execute返回值_selenium+python自动化101-使用execute_script() 方法获取 JavaScript 返回值...
  11. git push 的符号笔有什么用_Git 标签(tag)作用、分支区别及常用命令
  12. zbb20180117 汉字转拼音 pinyin4
  13. 2015-2020年各类国际会议与期刊基于图像的三维对象重建论文综述(7)——Datasets
  14. matlab虚拟现实之建立simulink虚拟现实工具箱的使用
  15. C/C++ 编译器全面采用 LLVM
  16. Mac电脑下配置maven环境变量
  17. python小孩子学有什么用_小孩子为什么一定要学习Python编程
  18. java log4j 动态配置_动态更改log4j日志级别
  19. DDIA - 第5章 数据复制
  20. python自动填写网页数据并提交_python实现问卷星网站的自动填写

热门文章

  1. 前程无忧响应整改,推出企业账户个人实名、虚拟号、简历水印等措施
  2. 访问学者出国申请可以分为哪几类?
  3. html手机改club,手机省电大全,快点GET起来吧!
  4. sakai的相关概念
  5. 年终盘点丨2017人工智能十大关键词,收购、政策、场景创新上榜
  6. Delphi StyleControls之标题栏Tabs
  7. 公司已注销,名下商标应该如何处理?
  8. android百度脱壳,[原创]百度加固逆向分析
  9. idea实现简单servlet的登录
  10. 关于实现手机号,身份证号加密解密解决方案