Встроенная база данных с одновременным чтением и записью - PullRequest
0 голосов
/ 05 февраля 2019

Я ищу решение для базы данных для одновременной проблемы записи и чтения .Мне нужна встроенная база данных , которая будет записана одним процессом записи .Одна и та же база данных будет прочитана одним процессом чтения , и эти процессы будут выполняться одновременно.

Я смотрел на такие решения, как RocksDB , но где у нас может быть несколько считывателей и один писатель, но у считывателя нет самого последнего представления базы данных после ее открытия один раз и, следовательно, должен снова открыть БД.

Любая помощь будет отличной.

РЕДАКТИРОВАТЬ

Код, который я написал для RocksDB -

writer.cc

#include <cstdio>
#include <string>
#include <unistd.h>
#include <iostream>

#include "rocksdb/db.h"
#include "rocksdb/slice.h"
#include "rocksdb/options.h"

using namespace rocksdb;

std::string kDBPath = "./db";

int main() {
  DB* db;
  Options options;
  options.IncreaseParallelism();
  options.OptimizeLevelStyleCompaction();
  options.create_if_missing = true;

  Status s = DB::Open(options, kDBPath, &db);
  assert(s.ok());

  for (int i = 0 ; ; i++) {
    int key = i;
    Slice kslice((char*)&key, sizeof(int));
    int value = i*i;
    Slice vslice((char*)&value, sizeof(value));
    s = db->Put(WriteOptions(), kslice, vslice);
    std::cout <<  "writing " << i << " : " << i*i << std::endl;
    assert(s.ok());
    sleep(1);
  }
  delete db;
  return 0;
}

Выходные данные, как и ожидалось:

writing 0 : 0
writing 1 : 1
writing 2 : 4
writing 3 : 9
writing 4 : 16
writing 5 : 25
writing 6 : 36
writing 7 : 49
writing 8 : 64
writing 9 : 81
...

reader.cc

#include <cstdio>
#include <string>
#include <unistd.h>
#include <iostream>

#include "rocksdb/db.h"
#include "rocksdb/slice.h"
#include "rocksdb/options.h"

using namespace rocksdb;
using namespace std;

std::string kDBPath = "./db";

int main() {
  DB* db;
  Options options;
  options.IncreaseParallelism();
  options.OptimizeLevelStyleCompaction();

  Status s = DB::OpenForReadOnly(options, kDBPath, &db);
  assert(s.ok());
  int i = 0;

  while(true) {
    sleep(1);
    std::string value;
    Slice kslice((char*)&i, sizeof(int));
    Status s = db->Get(ReadOptions(), kslice, &value);
    if (!s.ok()) {
      std::cout << i << " " << s.ToString() << std::endl;
      break;
    }
    int a;
    memcpy(&a, value.c_str(), sizeof(a));
    std::cout << i << ":" << a << std::endl;
    i++;
  }
  delete db;
  return 0;
}

Вывод (начинается после добавления ключа 3, а не ключа 4)

0:0
1:1
2:4
3:9
4 NotFound: 

Одно из возможных решений, которое я попробовал, это:

  Iterator* it = db->NewIterator(ReadOptions());
  int start = 0;
  Slice kslice((char*)&start, sizeof(int));
  it->Seek(kslice);
  bool flag = true;

  while (true) {
    int key, value;
    for ( ; it->Valid() ; it->Next()) {
      memcpy(&key, it->key().ToString().c_str(), sizeof(int));
      memcpy(&value,  it->value().ToString().c_str(), sizeof(int));
      cout << key << " - " << value << endl;
      if (!it->status().ok()) {
        cout << s.ToString() << endl;
        flag = false;
      }
    }
    if (!flag)
      break;
    sleep(1);
    Status s = DB::OpenForReadOnly(options, kDBPath, &db);
    assert(s.ok());
    Slice kslice((char*)&key, sizeof(int));
    it = db->NewIterator(ReadOptions());
    it->Seek(kslice);
    it->Next();
  }

И вывод такой, как ожидалось:

writing 0 : 0
writing 1 : 1
writing 2 : 4
writing 3 : 9
writing 4 : 16
writing 5 : 25
writing 6 : 36
writing 7 : 49
writing 8 : 64
writing 9 : 81
...

Однако я хочу избегать чтения базы данных снова и снова при каждом обновлении.

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

RocksDB явно задокументирована, чтобы поддерживать многопоточный параллелизм только в одном процессе.Вы не можете безопасно использовать его из нескольких процессов.

LMDB явно задокументирована для поддержки многопроцессорности, а считыватели и записывающие устройства LMDB работают без блокирования друг друга.Он будет делать то, что вы хотите.

0 голосов
/ 06 февраля 2019

Я рекомендую BerkeleyDB (BDB).Вы можете выполнять параллельные операции чтения и записи в разных процессах без каких-либо проблем.База данных заботится о согласованности, вам не нужно явно использовать какие-либо блокировки.

Другая известная база данных, LMDB (база данных с отображением памяти для осветления), разработанная в качестве замены для BDB.

Естьеще несколько встроенных баз данных.Эти два могут соответствовать вашим потребностям.

Раскрытие информации: в прошлом я использовал BDB в приложении.

...