Coder Social home page Coder Social logo

terkwood / augustdb Goto Github PK

View Code? Open in Web Editor NEW
7.0 2.0 1.0 313 KB

Key/value store backed by LSM Tree architecture.

License: MIT License

Elixir 80.45% SCSS 0.70% CSS 11.44% JavaScript 4.70% HTML 2.71%
elixir key-value-store demo lsm-tree sstables phoenix database learning-exercise

augustdb's People

Contributors

terkwood avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

icodein

augustdb's Issues

Partitioning

Use consistent hashing and vnodes to partition data

Create sparse index for SSTables

Seeking thru a few KB of data on disk is inexpensive. By keeping a sparse index of entries, we can hold byte offsets for many different keys in memory, even if our total data footprint is large.

SSTable compaction

  • Run periodically: use Jose Valim code instead of :timer.apply_interval
  • merge N tables by streaming the files side by side. Look at first key in each file, copy the lowest key to the output file, and repeat
  • do nothing if there is only one table , or no tables

Commit log

Append

  • Append to commit log before writing to memtable
  • Manage tombstones
  • Write TSV
  • Record monotonic time

Replay

  • Call CommitLog.replay() on app startup
  • Read every value since the beginning of the log, and push each one into memtable.
  • Read TSV
  • Do not update SSTable files
  • test escaping -- append doesn't bother with it. Does NimbleCSV parsing step on some values, e.g. \n?

Discard on Memtable flush

Background

An amusing article on Commit Log from Knoldus.

Flush memtable when it reaches multiple megabytes

strategy

Run a GenServer which holds a Map tracking size per key and an int tracking total memtable size. Update total incrementally. Trigger flush when reaching limit. Clear GenServer on flush

PXL_20210801_133219081-01

Make sure you size both the key and the value

this ticket creates some debt

For #51 (binary SSTables) , we need to consider this new section of code

Fix memtable seek

seek is now broken due to #29

The index is stored as an erlang term-to-binary

write the index as a separate file

Trim commit log

Trim commit log

See #18

Rough example: Mono time every second

-576460585406903497
-576460584406903735
-576460583406900449
-576460582406743977
-576460581406902914
-576460580406900571
-576460579406903413
-576460578406903531
-576460577406903611
-576460576406902549
-576460575406903716
-576460574406903760
-576460573406923925
-576460572406643840
-576460571406898130
-576460570406895297
-576460569406901522

Write idx files as map

See SSTable and Compaction modules

It's currently a list

You can remove the Enum.find calls

Store checksum in commit log

Unexpected failure such as power loss can cause partial writes. Store a checksum of the kv in commit log. Then on replay, we can detect malformed commit log records and discard them

Query all SSTables

If you find a :tombstone, stop. Otherwise keep searching backwards thru time until you run out of files.

Binary SSTables

Goal

Stop using TSV for SSTable storage. Use a binary format with explicit lengths for keys and values.

Format

value records

  1. Length of key in bytes
  2. Length of value in bytes
  3. Raw key, not escaped
  4. Raw value, not escaped

tombstone records

  1. Length of key in bytes
  2. -1 to indicate tombstone
  3. Raw key, not escaped

Subtasks

Notes

SS table compression

Compress the blocks referred to by sparse index #46

design

Erlang stdlib has an interface to zlib, which looks like a good starting point. Use gzip method so that we can compare checksums of uncompressed payloads to the footer bytes of compressed payloads (#79 & #80).

tasks

  • rework dump : store gzipped payload
  • rework compaction : store gzipped payload
  • rework query

prereqs

escaped double quotes break in commit.log

problem

curl -X PUT  -d value='no no  "try dbl" \nno\t\t new\n meh'  http://localhost:4000/api/values/3

then restart the app and when commit.log is read, it will crash

[error] Task #PID<0.417.0> started from AugustDb.Supervisor terminating
** (NimbleCSV.ParseError) unexpected escape character " in "3\tno no  \"try dbl\" \\nno
\\t\\t new\\n meh\t-576460747596327185\n"
    (august_db 0.1.0) deps/nimble_csv/lib/nimble_csv.ex:422: CommitLogParser.separator/
5

solution

ditch TSV entirely: #78

Benchmark Planning

integration tests in the existing project

Read the Phoenix testing manual https://hexdocs.pm/phoenix/testing.html

Or you could try to write some integration tests with https://github.com/boydm/phoenix_integration

end to end

Maybe try using finch for http requests in a standalone app https://github.com/keathley/finch

Alternatively you could write this in rust and leverage https://bheisler.github.io/criterion.rs/book/getting_started.html

Finally, There's trusty ol jmeter https://jmeter.apache.org/

unit test benchmarks

Test Zip, Memtable using https://elixirschool.com/en/lessons/libraries/benchee/

faker data

https://github.com/elixirs/faker#usage

Use bloom/cuckoo filters to reduce SSTable reads

Goal

Using SSTables, it takes a long time to determine that a certain record does not exist. In the case where there is neither a value nor a tombstone associated with a key, you need to read through all SSTables before you can return a negative result.

You can use a bloom or cuckoo filter to speed up queries for kv pairs which don't exist. These probabilistic data structures allow you to (mostly) determine set membership.

When the set membership test returns false, you can rely on the result. The K/V pair definitely does not exist.

When the set membership test returns true, there's a possibility that it's a false positive -- it may not be in the given table.

when to create them in memory

Background

https://stackoverflow.com/a/39331778

https://docs.datastax.com/en/archived/cassandra/3.0/cassandra/dml/dmlAboutReads.html

Candidate libraries

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.