2009-08-18 3 views
0

Je construis quelque chose qui s'apparente à Google Analytics et actuellement je fais des mises à jour de base de données en temps réel. Voici le flux de travail pour mon application:Comment puis-je reporter des mises à jour de base de données dans Rails?

  1. utilisateur fait une requête API RESTful
  2. je trouve un enregistrement dans une base de données, le retour comme JSON
  3. -je enregistrer le compteur de demande de l'utilisateur dans la base de données (c.-à- si l'utilisateur fait 2 appels API , j'incrémente le compteur de requêtes pour l'utilisateur par '2').

1 et 2 sont très rapides en SQL - ce sont des SELECT. # 3 est vraiment lent, parce que c'est une mise à jour. Dans le monde réel, ma base de données (MySQL) n'est PAS mise à l'échelle. Selon New Relic, # 3 prend la plupart du temps - jusqu'à 70%! Je pense que je dois arrêter de faire des opérations DB synchrones. À court terme, j'essaye de réduire les écritures de DB, donc je pense à un hachage global (disons déclaré dans environment.rb) qui est accessible à partir de mes contrôleurs et modèles auxquels je peux écrire au lieu d'écrire au DB. Chaque fois que je peux avoir une tâche écrire les mises à jour qui doivent être écrites dans la base de données.

Questions:

  1. Est-ce son raisonnable? Des pièges?
  2. Est-ce que je rencontrerai des problèmes de concurrence?
  3. Comment cela se compare-t-il avec l'écriture de journaux dans le système de fichiers et l'importation ultérieure?
  4. Devrais-je utiliser un système de mise en file d'attente des messages à la place, comme Starling? Des recommandations?

PS: Voici la requête incriminée - toutes les colonnes d'intérêt sont indexés:

MISE À JOUR statistics_api SET count_request = COALESCE (count_request,?) +? OERE (id =?)

Répondre

0

Procédez plus tard avec DelayedJob.

Modifier: Si votre base de données est touchée au point qu'une UPDATE ralentit sensiblement vos requêtes, vous devriez peut-être envisager de configurer une architecture de base de données maître-esclave.

+0

Merci de mettre à jour le lien, ecoologic! –

1

Votre solution de hachage semble être un peu trop complexe. Cette série de diapositives est un perspicace et mise à jour ressource qui traite votre tête d'émission sur:

Ils disent que la chose la plus simple serait:

Thread.new do 
    MyModel.do_long_thing 
end 

Mais le pilote mysql Ruby bloque, donc une requête mysql dans ce thread pourrait toujours bloquer votre requête. Vous pouvez utiliser mysqlplus en tant que pilote et obtenir des requêtes non bloquantes, mais nous obtenons maintenant une solution assez complexe et spécialisée.

Si vous voulez vraiment que cela de votre cycle de demande, mais peut épargner verrouiller le serveur pour cela, vous pouvez faire quelque chose comme:

MyController 
    after_filter :do_jobs 

    def index 
    @job = Proc.new{ MyModel.do_long_thing } 
    end 

private 

    def do_jobs 
    return unleses @job 
    @job.call 
    end 

end 

Je serais abstraite dans ApplicationController plus, mais vous obtenez l'idée. Le processus diffère les mises à jour jusqu'à la fin de la demande.

Si vous êtes sérieux au sujet des processus asynchrones et d'arrière-plan, vous devrez examiner les différentes options disponibles et décider de ce dont vous avez besoin. Matt Grande a recommandé DelayedJob - c'est un choix très populaire en ce moment, mais si votre serveur entier est embourbé avec des écritures de base de données, je ne le suggérerais pas. Si ce n'est qu'une mise à jour particulièrement lente, mais que votre serveur n'est pas surchargé, c'est peut-être une bonne solution. J'utilise actuellement Workling avec Starling dans mon projet le plus complexe. Workling a été assez extensible, mais Starling a été un peu moins que l'idéal. L'un des avantages de Workling est la possibilité d'échanger des backends, ce qui nous permet de quitter Starling si cela devient un gros problème.

Si votre serveur est encombré d'écritures, vous devrez envisager de le mettre à l'échelle quelle que soit l'approche de votre tâche asynchrone.

Bonne chance! Il semble que votre application est en pleine croissance :-)

Questions connexes