In Memory Datenbank mit Umgebungsvariablen

von Markus Berger am Freitag, 26. April 2024

Einleitung

Manchmal benötigt man eine einfache und generische Variante um Daten zwischen Anwendungen auszutauschen welche zu dem nur für eine gewisse Zeit gültig sind. Außerdem sollte der Dienst keine weiteren Abhängigkeiten benötigen um den Betrieb und die leichte Verteilung zu ermöglichen und auf allen Systemen laufen.

Server-Umsetzung

Realisieren kann man dies einfach und sicher z.B. mit der Programmiersprache Nim und einem Web-Framework. Die Datenspeicherung selbst wird in den Umgebungsvariablen der Anwendung realisiert und die Schlüssel entsprechen Pfaden die intern mit base64-Kodierung umgesetzt werden. So lassen sich einfach auch größere Datenmengen schnell teilen. Eine Beispielumsetzung ist im Projekt envmw zu finden.

Client

Als Client kann jede http-fähige Anwendung eingesetzt werden. Hier ein Beispiel auch in Nim:

import os
import std/[times, asyncdispatch, strformat, strutils]
import httpclient, httpcore
import jsony

type
  KV = object
    key: string
    value: string
    expire: float

var
  data: KV
  t1, t2: float
  n = 500
  client: HttpClient

proc twrite(data: KV) {.async.} =
  let client = newAsyncHttpClient()
  #client.headers = newHttpHeaders({"Content-Type": "application/json"})
  discard await client.postContent("http://127.0.0.1:6380/set",
      body = data.toJson())
  client.close()


proc main() {.async.} =
  while true:
    t1 = epochTime()
    for i in 1 .. n:
      data.key = fmt"/app/part1/subpart3/key{i}"
      data.expire = i/10
      data.value = fmt"{epochTime()=}, {i=}"
      await twrite(data)
    t2 = epochTime()

    echo fmt"{(t2-t1)/n.toFloat() * 1000} ms/req"
    client = newHttpClient()
    let key = "/app/part1/subpart3/key10"
    echo client.getContent(fmt"http://127.0.0.1:6380/get{key}").strip()
    sleep(500)
    echo client.getContent(fmt"http://127.0.0.1:6380/get{key}").strip()
    sleep(600)
    assert client.getContent(fmt"http://127.0.0.1:6380/get{key}") == "\n"
    client.close()


when isMainModule:
  waitFor main()

Zusatzfunktionen

In envmw steht noch eine ping-Funktion zur Verfügung und mit /keys können alle verfügbaren Schlüssel erfragt werden.

Datenspeicherung

Es ist natürlich auch möglich die Daten auf dem Server, z.B. durch ein Signal an diesen zu speichern. Hier könne man die Key-Value Paare z.B. als Symlink in base64 Kodierung effizient im Dateisystem abspeichern. Hier ein Beispiel in shell-script

ln -s $(echo $VALUE | base64) $KEY
RVALUE = $(readlink $KEY | base64 -d)