3

merci pour votre temps d'abord ... après toute la recherche sur google, github et ici, et a obtenu plus confus au sujet des grands mots (partition/tesson/fedorate), je me dis que je dois décrire le problème spécifique que j'ai rencontré et Demande autour de toi.Comment faire fonctionner ActiveRecord avec des bases de données/tables partitionnées/partagées héritées?

Mes bases de données de l'entreprise traite des utilisateurs massifs et les commandes, donc nous avons divisé les bases de données et des tables de différentes manières, certains sont décrits ci-dessous:

way    database and table name  shard by (maybe it's should be called partitioned by?) 
YZ.X   db_YZ.tb_X     order serial number last three digits 
YYYYMMDD.  db_YYYYMMDD.tb    date 
YYYYMM.DD  db_YYYYMM.tb_ DD    date too 

Le concept de base est que les bases de données et tables sont séparées acording à un champ (pas nessissarily la clé primaire), et il y a trop de bases de données et trop de tables, de sorte que l'écriture ou la génération magique d'une database.yml config pour chaque base de données et un modèle pour chaque table n'est pas possible ou du moins pas la meilleure solution . J'ai examiné les solutions magiques de drnic, et datafabric, et même le code source d'enregistrement actif, peut-être que je pourrais utiliser ERB pour générer database.yml et faire une connexion de base de données autour du filtre, et peut-être que je pourrais utiliser named_scope le nom de la table pour trouver, mais les opérations de mise à jour/création sont limitées à "self.class.quoted_table_name" de sorte que je ne pourrais pas facilement résoudre mon problème. Et même je pourrais générer un modèle pour chaque table, parce que sa quantité est jusqu'à 30 plus.

Mais ce n'est tout simplement pas sec!

Ce que je besoin est une solution propre comme le DSL suivante:

class Order < ActiveRecord::Base 
    shard_by :order_serialno do |key| 
     [get_db_config_by(key), #because some or all of the databaes might share the same machine in a regular way or can be configed by a hash of regex, and it can also be a const 
     get_db_name_by(key), 
     get_tb_name_by(key),   
     ] 
    end 
end 

Quelqu'un peut-il me illuminera? Toute aide serait grandement appréciée ~~~~

Répondre

1

Le deuxième cas (où seuls les changements de nom de base de données) est assez facile à implémenter avec DbCharmer. Vous devez créer votre own sharding method dans DbCharmer, cela retournerait un hash de paramètres de connexion basé sur la clé.

deux autres cas ne sont pas pris en charge tout de suite, mais ils pourraient être facilement ajoutés à votre système:

  1. Vous implémenter la méthode de sharding qui sait comment traiter les noms de base de données dans votre fragmentées dabatase, cela vous donnera une possibilité de faire shard_for(key) appels à votre modèle pour changer de connexion db.

  2. vous ajoutez une méthode comme ceci:

    class MyModel < ActiveRecord::Base 
        db_magic :sharded => { :sharded_connection => :my_sharding_method } 
    
        def switch_shard(key) 
        set_table_name(table_for_key(key)) # switch table 
        shard_for(key)      # switch connection 
        end 
    end 
    
  3. Maintenant, vous pouvez utiliser votre modèle comme celui-ci:

    MyModel.switch_shard(key).first 
    MyModel.switch_shard(key).count 
    

    et, étant donné que vous avez shard_for(key) résultats d'appels renvoyés par la méthode switch_shard, vous pouvez l'utiliser comme ceci:

    m = MyModel.switch_shard(key) # Switch connection and get a connection proxy 
    m.first      # Call any AR methods on the proxy 
    m.count 
    
+0

Merci pour votre solution détaillée, c'est très éclairant. Pourtant, il semble qu'il y ait un problème fatal: set_table_name est une méthode de classe, et son influence est à l'échelle de la classe, je ne peux pas l'étendre à l'objet spécifique. C'est pourquoi je pense à quelque chose de plus interne, comme "générer par magie un modèle pour chaque table" qui semble être utilisé dans votre solution magique (travaillant toujours à comprendre la source de DbCharmer). Si possible, je voudrais l'ajouter dans DbCharm, mais il y a un autre problème fatal, DbCharmer n'a pas de tests unitaires ... Alors, comment puis-je éviter de casser quelque chose pendant le processus? – Utensil

+0

DbCharmer prend en charge la commutation de connexion étendue. Vous pouvez toujours faire MyModel.on_db (: foo) {...} ou MyModel.switch_shard (key) {...} et cela ne ferait que changer de connexion dans un bloc. Comme pour les tests, il y a un projet séparé avec des spécifications (presque 100% couvrant le code de la gemme): https://github.com/kovyrin/db-charmer-sandbox – kovyrin

1

Si vous voulez ce DSL particulier, ou quelque chose qui correspond à la logique derrière le sharding hérité, vous aurez besoin de creuser dans ActiveRecord et écrire une gemme pour vous donner ce genre de aptitude. Toutes les solutions existantes que vous mentionnez n'ont pas nécessairement été écrites en tenant compte de votre situation. Vous serez peut-être capable de plier n'importe quel nombre de solutions à votre volonté, mais à la fin vous devrez probablement écrire du code personnalisé pour obtenir ce que vous cherchez.

+0

Merci pour votre réponse! J'ai creusé dans la source AR, et j'ai creusé dans la source de la solution différente que j'ai trouvée. J'ai fait tout cela pour trouver le moyen d'écrire mon propre plugin pour AR. L'une des solutions les plus proches est sharded_database plugin, bien qu'elle ne supporte pas la partition de table ... Je suppose que "class << self; set_table_name; end" pourrait me donner l'opportunité de changer le nom de la table pour chaque instance AR. Mais le coût, je ne sais pas. Et changer la connexion de la base de données à chaque fois, renoncerait à tous les avantages de la piscine ... En posant la question, j'essaie de chercher des gens dans la même situation ... – Utensil

+0

S'il se trouve qu'il y a un design élégant avec peu de contact et pirater sur AR, je serais grandement apprécié pour la lumière ... – Utensil

1

Cela ressemble, dans ce cas, vous ne devriez pas utiliser SQL.

Si les ensembles de données sont gros et peuvent être exprimés en paires clé/valeur (avec une légère dénormalisation), vous devriez vous pencher sur les solutions couchDB ou autres solutions noSQL. Ces solutions sont rapides, entièrement évolutives et basées sur REST. Elles sont donc faciles à développer, à sauvegarder et à répliquer.

Nous avons tous réussi à résoudre tous nos problèmes avec le même outil (Croyez-moi, j'essaie aussi).

Il serait beaucoup plus facile de passer à une solution noSQL puis de réécrire activeRecord.

+0

Merci pour votre réponse! C'est toujours génial d'avoir des solutions ouvertes ~ CouchDB est une bonne chose. Je * aime * erlang. Malheureusement, non-SQL dans mon cas n'est pas une option. Les bases de données mysql et de nombreux autres programmes C/C++ sont la majorité des entreprises réelles et sérieuses, j'essaie juste d'utiliser des rails pour leur parler. – Utensil

Questions connexes