Czy przechowywanie plików w Cassandra to dobry pomysł?

0

Jest taka architektura:

  • aplikacja Spring Boot (wiele instancji, wiele serwerów)
  • baza danych ScyllaDB (Cassandra przepisana na C++)
  • load balancer (kieruje ruch na losowy serwer z aplikacją)

Potrzebuję przechowywać duże pliki, w tym upload z możliwością wznawiania i download.

Jednym ze sposobów jest podzielenie plików na małe fragmenty:

CREATE TABLE IF NOT EXISTS files
(
  id          UUID,
  file_name   TEXT STATIC,
  size_bytes  INT STATIC,
  chunk_no    UUID,
  data        BLOB,
  PRIMARY KEY (id, chunk_no)
);

Jednak nasuwają się pewne wątpliwości:

  1. Kompaktowanie w Cassandrze/Scylli może doprowadzić do gwałtownego wzrostu zajmowanego miejsca.

  2. Czy nie dojdzie do zablokowania wątków, jeśli aplikacja Spring Boot będzie pośredniczyć zarówno przy uploadzie jak i przy downloadzie plików? Algorytm pobierania działałby tak:

  • policz liczbę kawałków na podstawie rozmiaru pliku
  • dla każdego pozostałego kawałka (to może trwać bardzo długo):
    • pobierz kawałek z bazy
    • wrzuć go do odpowiedzi (w Springu prawdopodobnie przez StreamingResponseBody)

Jeśli mamy 10 wątków i zablokujemy w ten sposób wszystkie wątki, to możemy doprowadzić, że aplikacja przestanie być dostępna dla innych użytkowników?

Jakie są jeszcze inne wady takiego rozwiązania?

Jak powinno się prawidłowo zrealizować rozproszony system plików? Czy istnieją gotowe rozwiązania open source? Istotne jest też, aby dało się ograniczyć dostęp do plików na podstawie informacji zapisanych w bazie danych (czyli sprawdzamy, czy użytkownik, który chce pobrać plik, ma dostęp do elementów powiązanych tym plikiem).

0

A nie lepiej jakiś CDN?

1

Dlaczego chcesz pliki trzymać w bazie, a nie w blob storage np. S3/GCS albo jakis wlasny serwer plików?

Odnosnie watkow - operacje dlugotrwajace powinny byc procesowane na dedykowanych pulach watkow. Moze w ogole powinny byc do tego dedykowane serwisy albo instancje?

0

To jakie serwery polecacie (do postawienia lokalnie, a nie w chmurze jak S3/GCS)? I jak wygląda kontrola dostępu? Zalogowany użytkownik, który ma dostęp do obiektu powiązanego z tym plikiem, powinien móc go pobrać, ale inna osoba już nie. Najlepiej by to zobaczyć na przykładzie.

A co do wątków, być może przejście na Spring Reactor rozwiązałoby ten problem,

NoSQL-owe przechowalnie plików to żadna nowość, istnieje trochę takich rozwiązań, lecz nie zawsze to jest najlepszy pomysł, zwłaszcza w przypadku Cassandry lub ScyllaDB - ktoś pisał o tym pracę dyplomową i jedną z pułapek było właśnie kompaktowanie, a druga jak mi się zdaje, to będzie z wątkami w Javie (trzeba by w jakiś sposób dać większy priorytet normalnemu ruchowi, a nie obsłudze plików), ale to musiałbym sprawdzić.

Może macie jeszcze inne pomysły?

1

Strumieniowaniem i wysyłaniem plików to powinien się zajmować serwer www, bo do tego jest wyspecjalizowany, a nie wątek w Javie. Tego nie zrobisz w ten sposób dobrze, za to jest to dobry sposób na zabicie serwera.

Polecam do tego serwer nginx i szukanie w internecie: "nginx streaming", "nginx sendfile", a same pliki radzę przechowywać po prostu na dysku, w bazie danych jedynie ścieżki do nich.

Jedyny problem to zbyt duża ilość plików w jednym katalogu - zaczyna spadać czas dostępu i robią się problemy z indeksami systemu plików.

Dlatego trzeba opracować algorytm tworzenia podkatalogów o głębokim zagłębieniu - np. w oparciu o numeryczne id pliku w bazie lub crc64 nazwy pliku.

Ja mam taki algorytm opracowany, nie tworzy więcej niż x plików w jednym katalogu i y podkatalogów w danym katalogu, natomiast zagłębienie jest teoretycznie nieskończone w oparciu o numeryczny id. Działa doskonale przy kilkuset tysiącach plików jakie muszę obsługiwać, które zajmują łącznie kilkadziesiąt GB.

1 użytkowników online, w tym zalogowanych: 0, gości: 1