2011-01-29 1 views
0

Salutations Gerbeurs.Comment concevoir et tester des _lots_ de données simultanées dans des rails?

Nous travaillons sur un projet qui stocke des données de suivi de seconde à seconde pour les participants à des expériences psychologiques. Notre design actuel a un client Flash qui recueille 60 secondes d'appariements horodatage/activité, puis publie les données sous forme de chaînes, avec une petite métadonnée de participant à notre application rails (3.0.3)/MySQL (5.1). Modifier Nous utilisons la vanille Passenger/Nginx pour l'avant. Rails divise les chaînes horodatage/activité dans des réseaux parallèles, génère une seule instruction d'insertion SQL brute, et lui enfonce alors tout dans une table massive, à savoir: (code simplifié)

@feedback_data = params[:feedbackValues].split(",") 
@feedback_times = params[:feedbackTimes].split(",") 
inserts = [] 
base = "(" + @userid + "," + @studyid + "," 
@feedback_data.each_with_index do |e,i| 
    record = base + @feedback_times[i].to_s + "," 
    record += "'" + @feedback_data[i].to_s + "')" 
    inserts.push(record) 
end 
sql = "INSERT INTO excitement_datas (participantId, studyId, timestamp, activityLevel) VALUES #{inserts.join(", ")}" 
ActiveRecord::Base.connection.execute sql 

Rendement:

INSERT INTO STUDY_DATA (participantId, studyId, timestamp, activityLevel) 
VALUES (3,5,2011-01-27 05:02:21,47),(3,5,2011-01-27 05:02:22,56),etc. 

La conception a généré beaucoup de débats sur l'équipe. Les études auront 10 ou 100 participants simultanés. J'ai décalé l'intervalle POST de 60 secondes pour chaque client afin que les données entrantes soient distribuées de manière plus égale, mais je reçois encore beaucoup de prédictions catastrophiques. Quoi d'autre pouvons-nous faire/devrions-nous faire pour améliorer l'évolutivité de cette conception dans les rails? Quels outils/techniques puis-je utiliser pour prédire avec précision comment cela fonctionne en charge?

Merci beaucoup.

Répondre

1

Il s'agit plus d'un problème d'architecture que d'un problème de code. Votre code semble sain, et générer une seule requête SQL est une bonne approche. Quel est votre serveur d'application?

Si vous utilisez, par exemple, un serveur léger, les requêtes se bloqueront pendant que la base de données exécute la requête SQL, ce qui entraînera une application qui ne répond pas. En utilisant Passenger ou Unicorn, vous obtiendrez une augmentation de la concurrence, mais des requêtes sql assez lentes par requête.

Si vous êtes vraiment préoccupé par cette requête, vous pouvez essayer une couche intermédiaire Memcache ou RabbitMQ, qui stocke un travail pour chacune des demandes reçues. Ensuite, demandez à une tâche d'arrière-plan (ou à plusieurs d'entre eux) d'effectuer l'insertion lente. Memcache et Rabbit sont plus réactifs que Mysql et vous avez affaire à la requête brute. Cela signifie que la demande se terminera très rapidement et transférera le gros du travail à vos tâches. Delayed Job pourrait être quelque chose à regarder, ou Workling, ou Bunny/EventMachine for Rabbit.

La persistance de Memcache peut être un problème pour vous, je recommanderais donc Rabbit si vous aimez l'approche basée sur la file d'attente.

En plus de cela, vous pouvez regarder Apache Bench pour voir comment vous faites en fait déjà:

http://httpd.apache.org/docs/2.0/programs/ab.html

Questions connexes