热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

『每周译Go』YYDS!Go如何编写简单的内存键值数据库

从Postgres到Redis,再到Prometheus,我们都使用并从事过各种数据库的开发。我花了很多时间来阅读其中一些数据库的源代码,

4a835635d35f934aba3e565b577e5196.png

从 Postgres 到 Redis,再到 Prometheus,我们都使用并从事过各种数据库的开发。我花了很多时间来阅读其中一些数据库的源代码,对于那些像我一样好奇的少数人来说,他们有兴趣学习如何编写一个数据库。本书旨在记录这一过程。

GitHub-arriqaaq/flashdb:

FlashDB is an embeddable, in-memory key/value database in Go (with Redis like commands)

01

内存数据库 

传统数据库的数据主要保存在机械硬盘或者固态硬盘, 内存数据库则主要将数据保存在内存中,并通过消除对磁盘的访问来实现最小的响应时间。两者的不同主要体现在内存数据库是将数据保存在主存或者 RAM 中,而传统的数据库则是通过驱动磁盘来获取数据。

内存数据库相比传统数据库更不稳定,由于所有的数据都存储与管理在主存中,当计算机断电或 RAM 崩溃时,数据将会丢失。

内存数据库可以通过将每个操作存储在日志中或采取快照的方式在磁盘上持久化数据

02

目标 

我们的目标是用 Go 编写一个简单、快速、嵌入式和可持久化的键/值数据库,并且实现以下功能:

  • 支持类似 Redis 的数据结构string, hash, set, zset

  • 具有低延时和高吞吐量

  • 支持事务,ACID 语义

  • 仅可写入的持久化文件格式

  • 可以通过使用 TTL 来处理数据过期

03

开始

我们要建立的是一个非常简单的 KV(键/值)存储,以便让每个人都能轻松理解和实现。在 Go 中,有相当多的嵌入式键/值存储可用,以下是一些例子:

  • BadgerDB - BadgerDB 是一个完全用 Go 编写的嵌入式、可持久化、简单而快速的键值(KV)数据库。它旨在成为 RocksDB 等非基于 Go 实现的键值存储的高性能替代品

  • BoltDB - BoltDB 是一个基于 B+ 树的嵌入式 Go 键/值数据库

  • BuntDB - BuntDB 是一个应用于 Go 的嵌入式内存键/值数据库,具有自定义索引和地理空间支持

  • go-memdb - 基于不可变基数树的 Golang 内存数据库

  • nutsdb - 一个基于磁盘的键值存储

读起来容易做起来难。虽然我们可以通过阅读庞大的代码库来了解其内部结构,但这对很多人来说依旧是一个障碍。我们的初衷是为任何想学习关于如何编写一个简单的 ACID 数据库的新手提供桥梁。

NutsDB 是我在 2-3 年前读到的第一批简单易懂的代码之一。因此,我们选择由易于理解的组合库组成的FlashDB。

04

架构 

FlashDB 的架构很简单并且支持各种 Redis 命令。Redis 本质上不是一个普通的键值存储,而是一个数据结构服务器,支持不同种类的值。事实上,Redis 使用以下数据结构实现了各种类型。

27266d5c4869de8a0d97b51f492ee694.png

05

字符串

Redis 字符串类型是能与 Redis 键关联的最简单的值类型。由于 Redis 键是字符串,当我们把字符串类型也作为一个值时,实际上是把一个字符串映射到另一个字符串。这是用可变基数树(ART)实现的,这样可以很容易进行扫描。

  • String

 (https://github.com/arriqaaq/skiplist)

06

哈希

用哈希表示对象很方便,而实际上哈希中可放入的字段数量并没有实际限制(除了可用的内存),所以你可以在应用程序中以许多不同的方式使用哈希。这是用一个非常简单的 HashMap 数据结构实现的。

  • Hash

    (https://github.com/arriqaaq/hash)

07

集合 

Redis 集合是无序的字符串集合。我们可以对集合进行一些操作,比如检测某个元素是否已经存在,查找多个集合之间的交集、并集或差集等。这也是用一个简单的 HashMap 数据结构实现的。

  • Set

(https://github.com/arriqaaq/set)

08

有序集合 

有序集合是一种数据类型,类似于集合与哈希的混合体。和集合一样,有序集合也是由唯一的、不重复的字符串元素组成的。所以从某种意义上说,有序集合也是一个集合。

虽然集合内的元素并不是有序的,但有序集合中的每个元素都与一个浮点值相关,称为分数(该类型类似于哈希,因为每个元素都被映射到一个值)。

这是对用于字符串的跳表结构稍加修改实现的。

  • ZSet 

    (https://github.com/arriqaaq/zset)

09

持久化

虽然已经有了很多持久化机制,但我选择了一个简单的 append-only 日志设计方式,因为它比较容易实现和理解。

AOF(仅可写入的文件)记录了服务器收到的每一个写操作,这些操作将在服务器启动时再重放,重建原始数据集。命令的记录格式与 API 协议本身相同,以只写入的方式进行。当日志过大时,FlashDB 能够在后台分片处理日志。这是基于 wal 实现的。

  • Append Only Log

    (https://github.com/arriqaaq/aol)

总结

综上,FlashDB 仅依靠上述五个简单的库就完成了,具有事务与 ACID 支持,易于理解。但我希望这对任何有兴趣学习如何编写数据库的人来说都是一个有用的教程。

GitHub - arriqaaq/flashdb: 

FlashDB is an embeddable, in-memory key/value database in Go (with Redis like commands)

讲座

最近在 Golang meetup 上分享了这个项目,这是幻灯片的内容:

https://www.canva.com/design/DAE8sGRyC2o/ZCuCaezQ6dYA0Oq24QxjUQ/view?utm_content=DAE8sGRyC2o&utm_campaign=designshare&utm_medium=link&utm_source=publishsharelink

原文地址:

https://aly.arriqaaq.com/building-a-database-in-go

原文作者:Farhan Aly

本文永久链接:https://github.com/gocn/translator/blob/master/2022/w17_Writing_a_simple_in-memory_key-value_Database_in_Go.md

译者:张宇

校对:小超人

想要了解更多相关的内容,欢迎扫描下方👇 关注 公众号,回复关键词 [实战群]  ,就有机会进群和我们进行交流~

184dffc9c2e346e5bd0e4a7fc810ae6a.png

分享、在看与点赞,至少我要拥有一个叭~

add4ffbc9630b8ea10a4f443676fb76f.gif

511df96253cf3169783803c372e91595.gif


推荐阅读
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • 网络攻防实战:从HTTP到HTTPS的演变
    本文通过一系列日记记录了从发现漏洞到逐步加强安全措施的过程,探讨了如何应对网络攻击并最终实现全面的安全防护。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • This document outlines the recommended naming conventions for HTML attributes in Fast Components, focusing on readability and consistency with existing standards. ... [详细]
  • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
  • 本文详细介绍了 Apache Jena 库中的 Txn.executeWrite 方法,通过多个实际代码示例展示了其在不同场景下的应用,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
author-avatar
手机用户2602919091
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有