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.
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.
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.
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).
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.
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.
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.