2012-10-13 7 views
2

Je sais que cette question est posée plusieurs fois dans stackoverflow. Je poste cette question pour savoir quel sera le meilleur choix pour mon design. J'ai le schéma suivant pour les détails de mon travail.Dans la base de données relationnelle de mémoire

_unique_key  varchar(256) NULL 
_job_handle  varchar(256) NULL 
_data    varchar(1024) NULL 
_user_id   int(11) NULL 
_server_ip   varchar(39) NULL 
_app_version  varchar(256) NULL 
_state    int(11) NULL 
_is_set_stopped bool 

Quelle est l'opération que nous faisons sur ce tableau:

  1. Pour chaque travail que nous aurons une mise à jour et 10 requête de sélection sur ce tableau. Nous avons donc besoin de haute fréquence pour lire et écrire.
  2. Il existe de nombreuses applications qui manipulent ce tableau en faisant filtre:
    1. _unique_key
    2. _STATE
    3. is_set_stopped
    4. _user_id
  3. taille du champ _data varie de 5 Ko à 1 Mo en fonction du type d'application et de l'utilisateur.
  4. L'application peut mettre à jour l'attribut sélectif.

Solution nous avons pensé:

MySQL InnoDB

Je pense que MySQL ne va pas assez échelle en raison de besoins de lecture et d'écriture élevée.

MySQL Dans le tableau mémoire

problème avec cette solution est que

  1. Il ne supporte pas la taille du champ dynamique. Les tables MEMORY utilisent un format de stockage de ligne de longueur fixe. Les types à longueur variable tels que VARCHAR sont stockés en utilisant une longueur fixe. Source http://dev.mysql.com/doc/refman/5.0/en/memory-storage-engine.html
  2. sélectionnez pour .... la mise à jour verrouillera une table entière. Je ne sais pas ce sera un problème.

Redis

regard Redis aime un bon choix. Mais je pense que ma table n'est pas bonne pour le serveur de cache de valeur clé.

  1. Il supporte seulement l'ensemble des types de données. Je peux stocker seulement la chaîne dans la liste. J'ai besoin de stocker des champs comme JSON ou un autre format.
  2. Si les clients veulent mettre à jour un attribut particulier, ils doivent télécharger la valeur complète, puis effectuer l'analyse de l'objet et repasser au serveur. Peut-être que je me trompe est-il un moyen de faire cela?
  3. Le filtrage basé sur la valeur ne sera pas possible. Peut-être que je me trompe est-il un moyen de faire cela?

MySQL InnoDB sur le système de fichiers TMPFS

Ce regard prometteur. Mais ne le fera-t-il pas assez semblable à Redis ou MySQL dans la table de mémoire.

+1

Quelles sont vos exigences actuelles en matière de vitesse de lecture/écriture? –

+0

@ Joachim Isaksson. Le besoin actuel est de 1380 lectures et écritures par seconde pour une ligne complète et de 6900 lectures par seconde pour la colonne is_set_stopped. Le nombre augmentera en fonction du nombre de tâches augmentées sur le serveur. –

+0

Pourquoi croyez-vous que MySQL avec InnoDB ne peut pas être pertinent? Vous aurez besoin de l'accorder très bien ... –

Répondre

4

Dans cette question, vous confondez les performances brutes (efficacité) avec l'évolutivité. Ce sont des concepts différents.

Entre les moteurs InnoDB et de la mémoire, InnoDB est susceptible d'être la plus évolutive. InnoDB supporte le contrôle des accès simultanés multi-versions, a beaucoup d'optimisations pour gérer les conflits, donc il va gérer les accès concurrents bien mieux que le moteur de mémoire. Même si cela peut être plus lent dans certaines situations liées aux E/S.

Redis est un serveur monothread. Toutes les opérations sont sérialisées. Il a une évolutivité nulle. Cela ne veut pas dire que c'est inefficace. Au contraire, il supportera vraisemblablement plus de connexions que MySQL (en raison de sa boucle d'événements basée sur epoll), et plus de trafic (grâce à son implémentation sans verrou très efficace et à ses structures de données en mémoire).

Pour répondre à votre question, je voudrais essayer MySQL avec InnoDB. Si elle est correctement configurée (pas de validation synchrone, tampon de cache suffisant, etc ...), elle peut supporter un bon débit. Et au lieu de l'exécuter en haut sur tmpfs, je considérerais le matériel de SSD.

Maintenant, si vous préférez utiliser Redis (ce qui est un magasin relationnel BTW), vous pouvez certainement le faire. Il n'est pas nécessaire de sérialiser/désérialiser systématiquement vos données. Et le filtrage est en effet possible, à condition de pouvoir anticiper tous les chemins d'accès et de trouver une structure de données adaptée.

Par exemple:

  • un objet de hachage par emploi. La clé est _unique_key. Les champs du hachage doivent correspondre aux colonnes de votre table relationnelle.
  • un ensemble par valeur d'état
  • 2 jeux pour is_set_stopped
  • un ensemble par valeur userid

Pour chaque insertion professionnelle, vous devez pipeline les commandes suivantes:

HMSET job:AAA job_handle BBB data CCC user_id DDD server_ip EEE app_version FFF state GGG is_set_stopped HHH 
SADD state:GGG AAA 
SADD is_set_stopped:HHH AAA 
SADD user_id:DDD AAA 

Vous peut facilement mettre à jour n'importe quel champ individuellement à condition de maintenir les ensembles correspondants.

Vous pouvez effectuer des requêtes de filtrage en croisant les ensembles. Par exemple:

SINTER is_set_stopped:HHH state:GGG 

Avec Redis, le goulot d'étranglement sera probablement le réseau, en particulier si le champ de données est grande. J'espère que vous aurez plus d'emplois de 5KB que les emplois de 1MB. Par exemple 1000 écriture/s d'objets de 1 Mo représente 8 Go/s, probablement plus que ce que votre réseau peut supporter. Cela est vrai pour Redis et MySQL.

+0

aha merci. Je n'ai jamais pensé à la limitation du réseau. –

1

Je propose postgresql, il est plus capable (a plus de fonctionnalités et un meilleur soutien pour les requêtes et complexes types de données) que MySQL et a beaucoup d'options de réglage.

Si vous donnez suffisamment de mémoire à la mémoire postgresql et que vous réglez correctement les paramètres, elle mettra tout en mémoire cache.Vous pouvez également l'utiliser sur tmpfs si vous préférez et utiliser la réplication en continu vers une base de données sur disque pour obtenir une copie papier.

La réplication en continu a trois modes de fonctionnement de manière asynchrone, à la réception et sur fsync. Si vous utilisez le premier, asynchrone, vous n'avez pas besoin d'attendre une synchronisation sur disque sur le serveur de réplication, donc les mises à jour seront très rapides avec tmpfs. Puisque vous semblez avoir beaucoup de champs de texte, une autre fonctionnalité pourrait vous aider, postgresql peut stocker un vecteur de recherche de texte sur une ligne, et vous pouvez ajouter un index dessus et le mettre à jour via un trigger avec le contenu concaténé de toutes les lignes que vous recherchez. Cela vous donnera un incroyable coup de fouet lors de la recherche de texte sur plusieurs colonnes par rapport à tout ce que vous pouvez éventuellement écrire dans mysql.

Quelle que soit la base de données que vous utilisez:

Vous déclarez que _data est varchar [1024], mais vous dites qu'il contient 5K à 1 M de données? Est-ce réellement une goutte? Même si c'était une erreur dans la longueur mysql ne supporte pas les champs varchar de plus de 65535 octets de longueur! Je suppose que ce n'est pas mis à jour autant que les autres lignes, il pourrait être judicieux de séparer cela en deux tables, l'une avec les données statiques et l'autre avec les données dynamiques pour minimiser l'accès au disque.

Questions connexes