web-dev-qa-db-fra.com

Quelle base de données pourrait gérer le stockage de milliards / trillions d'enregistrements?

Nous envisageons de développer un outil pour capturer et analyser les données netflow, dont nous collectons d'énormes quantités de données. Chaque jour, nous capturons environ 1,4 milliard d'enregistrements de flux qui ressembleraient à ceci au format json:

{
   "tcp_flags": "0",
   "src_as": "54321",
   "nexthop": "1.2.3.4",
   "unix_secs": "1352234521",
   "src_mask": "23",
   "tos": "0",
   "prot": "6",
   "input": "105",
   "doctets": "186",
   "engine_type": "0",
   "exaddr": "2.3.4.5",
   "engine_id": "2",
   "srcaddr": "9.8.7.6",
   "dst_as": "12345",
   "unix_nsecs": "752265174",
   "sysuptime": "2943529544",
   "dst_mask": "24",
   "dstport": "80",
   "last": "2943523241",
   "srcport": "52672",
   "dpkts": "4",
   "output": "111",
   "dstaddr": "6.5.4.3",
   "first": "2943517993"
}

Nous aimerions pouvoir effectuer des recherches rapides (moins de 10 secondes) sur l'ensemble de données, probablement sur des tranches de temps étroites (intervalles de 10 à 30 minutes). Nous voulons également indexer la majorité des points de données afin de pouvoir effectuer des recherches sur chacun d'eux rapidement. Nous aimerions également avoir une vue à jour des données lors de l'exécution des recherches. Ce serait formidable de rester dans le monde open source, mais nous ne sommes pas opposés à la recherche de solutions propriétaires pour ce projet.

L'idée est de conserver environ un mois de données, ce qui représenterait environ 43,2 milliards d'enregistrements. Une estimation approximative que chaque enregistrement contiendrait environ 480 octets de données, équivaudrait à environ 18,7 téraoctets de données en un mois, et peut-être trois fois plus qu'avec les index. Finalement, nous aimerions accroître la capacité de ce système à stocker des milliards de documents.

Nous avons (très fondamentalement) évalué les candidats couchbase, cassandra et mongodb dans la mesure du possible pour ce projet, mais chacun propose ses propres défis. Avec couchbase, l'indexation est effectuée à intervalles et non pendant l'insertion des données, de sorte que les vues ne sont pas à jour, les index secondaires de cassandra ne sont pas très efficaces pour renvoyer les résultats car ils nécessitent généralement de scanner l'ensemble du cluster pour les résultats, et mongodb semble prometteur mais semble être beaucoup plus difficile à mettre à l'échelle car il est maître/esclave/fragmenté. Certains autres candidats que nous prévoyons d'évaluer sont elasticsearch, mysql (je ne sais pas si cela est même applicable) et quelques bases de données relationnelles orientées colonnes. Toute suggestion ou expérience du monde réel serait appréciée.

77
somecallmemike

Dans une entreprise pour laquelle je travaille, nous traitons une quantité similaire de données (environ 10 To de données consultables en temps réel). Nous résolvons cela avec Cassandra et je voudrais mentionner quelques idées qui vous permettront de faire O(1) recherche sur une base de données multi TBs. Ce n'est pas spécifique à Cassandra db cependant, vous pouvez également l'utiliser avec d'autres db.

Théorie

  • Éclatez vos données. Il n'y a aucun moyen qu'un seul serveur contienne de manière fiable et réaliste un tel volume de données.
  • Soyez prêt pour les pannes matérielles et les pannes de nœuds entiers, dupliquez les données.
  • Commencez à utiliser de nombreux serveurs principaux depuis le début.
  • Utilisez de nombreux serveurs de produits moins chers par rapport à ceux de haute performance haut de gamme.
  • Assurez-vous que les données sont réparties également entre les fragments.
  • Passez beaucoup de temps à planifier vos requêtes. Dérivez l'API à partir des requêtes, puis concevez soigneusement les tableaux. C'est la tâche la plus importante et la plus longue.
  • Dans Cassandra, vous pouvez concevoir une clé de colonne composite et accéder à cette clé dans O (1). Passez du temps à travailler dessus. Il sera utilisé pour accéder aux enregistrements consultables à la place de l'index secondaire.
  • Utilisez des rangées larges. Ils sont utiles pour stocker des événements horodatés.
  • N'effectuez jamais une analyse complète ou en fait une opération supérieure à O (Log N) sur un tel volume. Si vous avez besoin de plus que O (Log N), déchargez ces opérations vers les algorithmes Map-Reduce.

Entraine toi

  • Ne passez pas de temps à créer des images de système d'exploitation ou à installer des serveurs sur des machines physiques. Utilisez des fournisseurs basés sur le cloud pour un prototypage rapide. J'ai travaillé avec Amazon EC2 et je le recommande vivement pour sa simplicité, sa fiabilité et sa rapidité de prototypage.
  • Les machines Windows ont tendance à être plus lentes pendant le démarrage et prennent beaucoup plus de ressources en mode veille. Envisagez d'utiliser un système d'exploitation basé sur Unix. Personnellement, j'ai trouvé que le serveur Ubuntu était un système d'exploitation fiable, mais en plus il y a une assez bonne communauté à askubunt
  • Pensez à la mise en réseau, les nœuds doivent idéalement être proches les uns des autres pour permettre des commérages rapides et des échanges de métadonnées.
  • N'allez pas dans les cas extrêmes: des lignes de colonnes vraiment larges ou des familles de colonnes exceptionnellement longues (tables). Les meilleures performances sont obtenues dans les limites saines - si db prend en charge autant [~ # ~] n [~ # ~] lignes par conception, cela ne fonctionne pas ' Cela signifie qu'il fonctionne bien.
  • Notre recherche prend environ 3-5 secondes, beaucoup est dû aux nœuds intermédiaires entre l'interface utilisateur et la base de données. Considérez comment rapprocher les demandes de la base de données.
  • Utilisez un équilibreur de charge réseau. Choisissez-en un établi. Nous utilisons HAProxy, qui est simple, mais très rapide. Je n'ai jamais eu de problème avec ça.
  • Préférez la simplicité aux solutions complexes.
  • Recherchez des solutions open source gratuites, sauf si vous êtes soutenu par le budget de taille d'une entreprise. Une fois que vous utilisez plusieurs serveurs, les coûts d'infrastructure peuvent monter en flèche.

Je ne travaille pas pour Amazon et je n'ai aucune relation avec les équipes HAProxy et Ubuntu. Il s'agit d'une opinion personnelle plutôt que d'une promotion.

59
oleksii

Si je devais mettre cela dans SQL Server, je suggérerais une table quelque chose comme:

CREATE TABLE tcp_traffic
(
    tcp_traffic_id bigint constraint PK_tcp_traffic primary key clustered IDENTITY(1,1)
    , tcp_flags smallint    /* at most 9 bits in TCP, so use SMALLINT */
    , src_as int        /* Since there are less than 2 billion A.S.'s possible, use INT */
    , netxhop bigint    /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , unix_secs bigint  
    , src_mask int      /* an assumption */
    , tos tinyint       /* values are 0-255, see RFC 791 */
    , prot tinyint      /* values are 0-255, see RFC 790 */
    , input int         /* an assumption */
    , doctets int       /* an assumption */
    , engine_type int   /* an assumption */
    , exaddr bigint     /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , engine_id int     /* an assumption */
    , srcaddr bigint    /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , dst_as int        /* Since there are less than 2 billion A.S.'s possible, use INT */
    , unix_nsecs bigint /* an assumption */
    , sysuptime bigint  /* an assumption */
    , dst_mask int      /* an assumption */
    , dstport smallint  /* ports can be in the range of 0 - 32767 */
    , [last] bigint     /* an assumption */
    , srcport smallint  /* ports can be in the range of 0 - 32767 */
    , dpkts int         /* an assumption */
    , output int        /* an assumption */
    , dstaddr bigint    /* use a big integer for the IP address instead of storing
                            it as dotted-decimal */
    , [first] bigint    /* an assumption */
);

Il en résulte un besoin total de stockage estimé pour la table unique, sans aucun autre index de 5,5 TB pour 43,2 enregistrements d'abeille (vos besoins spécifiés). Ceci est calculé comme 130 octets pour les données elles-mêmes, plus 7 octets par ligne de surcharge, plus 96 octets par page de surcharge. SQL Server stocke les données dans des pages de 8 Ko, ce qui permet 59 lignes par page. Cela équivaut à 732 203 390 pages pour un seul mois de données.

SQL Server aime écrire sur le disque en blocs de 8 pages (64 Ko), ce qui équivaut à 472 lignes par E/S physique. Avec 16 203 enregistrements de flux générés chaque seconde, vous aurez besoin d'un taux d'E/S minimum de 34 IOps, garanti chaque seconde. Bien que cela ne soit pas énorme en soi, les autres E/S du système (SQL Server et autres) ne doivent jamais enfreindre ce taux nécessaire d'IOps. Par conséquent, vous auriez besoin de concevoir un système capable d'au moins un ordre de grandeur de plus d'IOps, ou 340 IOps soutenus - j'aurais tendance à estimer que vous avez besoin de 2 ordres de grandeur d'IOps plus durables pour garantir le débit.

Vous remarquerez que je ne stocke pas les adresses IP sous leur forme décimale à points. Cela permet d'économiser énormément sur le stockage (7 octets par adresse) et rend également l'indexation, la récupération, le tri et la comparaison des adresses IP bien plus efficaces. L'inconvénient ici est que vous devez convertir les adresses IP décimales en points en entiers de 8 octets avant de les stocker, puis revenir aux adresses IP décimales en pointillés pour l'affichage. Le code pour le faire est trivial, mais votre taux de lignes cela ajoutera une quantité substantielle de surcharge de traitement à chaque ligne de flux en cours de traitement - vous voudrez peut-être effectuer ce processus de conversion sur une machine physiquement différente de SQL Server.

La discussion des index dont vous avez besoin est une question totalement distincte car vous n'avez répertorié aucune exigence spécifique. La conception de cette table stockera les lignes de flux dans l'ordre physique de leur réception par SQL Server, le champ tcp_traffic_id Est unique pour chaque enregistrement et permet de trier les lignes selon l'ordre dans lequel elles ont été enregistrées (dans ce cas, très probablement relation un à un avec le moment de l'événement de flux).

41
Max Vernon

Je recommanderais HBase . Vous pouvez stocker toutes les données brutes dans une ou plusieurs tables HBase, selon ce que vous devez interroger. HBase peut gérer des ensembles de données volumineux et effectue un partitionnement automatique via les divisions de région.

De plus, si vous concevez bien les clés de ligne, vous pouvez obtenir des requêtes extrêmement rapides, même O(1). Notez que si vous récupérez un grand ensemble de données, cela restera lent car la récupération des données est une opération O(n).

Étant donné que vous souhaitez interroger dans chaque champ, je recommanderais de créer une table unique pour chacun d'eux. Exemple pour les données src_address, ayez une table qui ressemble à ceci:

1.2.3.4_timestamp1 : { data }
1.2.3.4_timestamp2 : { data }

Donc, si vous souhaitez interroger toutes les données à travers 1.2.3.4 à partir du 27 mars 12 h 00 jusqu'au 27 mars 12 h 01, vous pouvez effectuer une analyse de plage avec les lignes de début et d'arrêt spécifiées.

À mon humble avis, la conception des clés de ligne est la partie la plus critique de l'utilisation de HBase - si vous la concevez bien, vous pourrez effectuer des requêtes rapides ET stocker de gros volumes de données.

5
Suman

A dit ceci :

... nous ne sommes pas opposés à la recherche de solutions propriétaires pour ce projet

Je suggère de considérer base de données IBM Informix + TimeSeries datablade. En face de ce que certains disent, Informix est vivant et se passe très bien. La dernière version est sortie le mois dernier (mars/2013, version 12.10).

TimeSeries est comme un "plugin" (gratuit) capable de gérer des situations comme la vôtre.
Et vous pouvez l'utiliser en production avec la version gratuite de la base de données Informix ( édition Innovator-C ). (bien sûr, uniquement pour évaluer les parties techniques car la version gratuite a beaucoup de ressources limitées)

Ici vous pouvez vérifier un PDF de référence ce qui peut être utilisé comme référence. Voici deux présentations avec des exemples plus techniques: guide des nuls et - autres conseils

Je n'ai pas d'expérience personnelle avec TimeSeries , donc je ne peux pas convenir que ce sera "la solution", juste une suggestion à évaluer.

3
ceinmart

J'appuie la recommandation de regarder Informix TimeSeries. La littérature IBM affirme que TimeSeries peut stocker ce type d'informations dans 1/5 de l'espace et effectuer 5 fois plus vite que les tables relationnelles traditionnelles.

Des avantages supplémentaires seraient l'interface de table virtuelle qui peut faire apparaître les données TimeSeries comme des tables relationnelles traditionnelles pour l'utilisateur final (simplifiant le développement d'applications tout en bénéficiant des avantages de TimeSeries), une simple HA avec des nœuds HDR qui prennent désormais en charge les données TimeSeries dans la version 12.1 et le l'intégration des données TimeSeries dans Informix Warehouse Accelerator qui peut être utilisée pour accélérer les rapports d'entrepôt de données complexes et la possibilité de créer un prototype de solution TimeSeries dans Informix à l'aide des éditions gratuites Informix Developer ou Innovator-C.

2
Andrew