Système de connexion utilisateur
Un système qui enregistre les informations de connexion des utilisateurs. Nous avons simplifié les opérations et n'avons laissé qu'une seule table.
Conception de base de données relationnelle
mysql>select*fromlogin;
+---------+----------------+----- - -------+---------------------+
|id_utilisateur|nom|login_times|last_login_time|
+----- - ---+------+-------------+-------------------- - -------+
|1|kenthompson|5|2011-01-0100:00:00|
|2|dennisritchie|1|2011-02-0100:00:00|
| 3 |JoeArmstrong|2|2011-03-0100:00:00|
+---------+----------------+---- - ---------+---------------------+
La clé primaire de la table user_id, name représente le nom d'utilisateur, login_times représente le nombre de connexions de l'utilisateur, chaque fois qu'un utilisateur se connecte, login_times augmentera de lui-même et last_login_time sera mis à jour à l'heure actuelle.
Conception de REDIS
Convertir les données relationnelles en base de données KV. Ma méthode est la suivante :
Nom de la table clé : Valeur de la clé primaire : Nom de la colonne
Valeur de la colonne de valeur
Généralement, les deux points sont utilisés comme séparateur, ce qui est règles non écrites. Par exemple, dans le système php-adminforredis, les clés sont séparées par deux points par défaut, donc user:1user:2 et les autres clés seront divisées en un seul groupe. Ainsi, les données de relation ci-dessus sont converties en données kv et enregistrées comme suit :
Setlogin:1:login_times5
Setlogin:2:login_times1
Setlogin:3:login_times2
Setlogin:1:last_login_time2011-1-1
Setlogin :2 :last_login_time2011-2-1
Setlogin:3:last_login_time2011-3-1
setlogin:1:name"kenthompson"
setlogin:2:name"dennisritchie"
setlogin:3:name"JoeArmstrong"
Si la clé primaire est connue, vous pouvez utiliser les méthodes get et set pour obtenir ou modifier le nom de l'utilisateur, les heures de connexion et l'heure de la dernière connexion.
Les utilisateurs ordinaires ne peuvent pas connaître leur propre identifiant, ils connaissent seulement leur nom d'utilisateur, il doit donc y avoir une relation de mappage entre le nom et l'identifiant. La conception ici est différente de celle ci-dessus.
set"login:kenthompson:id"1
set"login:dennisritchie:id"2
set"login:JoeArmstrong:id"3
De cette façon, chaque fois que l'utilisateur se connecte, la logique métier est comme suit (version python), r est l'objet redis et name est le nom d'utilisateur connu.
#Obtenir l'identifiant de l'utilisateur
uid=r.get("login:%s:id"%name)
#Augmenter le nombre de connexions utilisateur
Ce qui suit est une phrase reformulée possible : ret = r.incr("login:%s:login_times" % uid)
#Mettre à jour l'heure de la dernière connexion de l'utilisateur
ret=r.set("login:%s:last_login_time"%uid,datetime.datetime. now ())
Si l'exigence est uniquement de connaître l'ID, de mettre à jour ou d'obtenir la dernière heure de connexion et le nombre de connexions d'un utilisateur, il n'y a pas de différence entre la base de données relationnelle et la base de données kv. L’un via btreepk et l’autre via hash, qui fonctionnent tous deux très bien.
Supposons qu'il existe la condition suivante pour trouver les N utilisateurs qui se sont connectés récemment. Les développeurs y jettent un coup d'œil et c'est relativement simple et peut être réalisé avec un seul SQL.
Veuillez sélectionner toutes les colonnes de la table "login", trier par la colonne "last_login_time" par ordre décroissant et limiter la taille du jeu de résultats à N
Une fois que le DBA aura compris les exigences, étant donné que la table sera plus grande dans le futur, il est construit sur l'index last_login_time. En accédant à N enregistrements en commençant par le côté le plus à droite de l'index, puis en effectuant N opérations de retour de table, le plan d'exécution a un effet significatif.
Quelles sont les conceptions des valeurs clés communes de la base de données Redis
Deux jours plus tard, une autre exigence est arrivée, et j'avais besoin de savoir qui s'était le plus connecté. Comment gérer le même type relationnel ? DEV a dit que c'était simple
select*fromloginorderbylogin_timesdesclimitN
DBA jette un œil et doit créer un index sur login_time. Pensez-vous qu'il y a quelque chose qui ne va pas ? Chaque champ du tableau a une citation principale.
La source du problème est que le stockage des données de la base de données relationnelle n'est pas assez flexible et que les données ne peuvent être stockées qu'à l'aide d'une table de tas disposée en lignes. Une structure de données unifiée signifie que vous devez utiliser des index pour modifier le chemin d'accès SQL afin d'accéder rapidement à une certaine colonne, et l'augmentation des chemins d'accès signifie que vous devez utiliser des informations statistiques pour vous aider, ce qui entraîne de nombreux problèmes.
Il n'y a pas d'index, pas de plan statistique et pas de plan d'exécution, c'est la base de données kv.
En réponse à la nécessité d'obtenir les N dernières données, la fonctionnalité dernier entré, premier sorti de la liste chaînée dans Redis est très adaptée. Nous ajoutons un morceau de code après le code de connexion ci-dessus pour maintenir une liste chaînée de connexion et contrôler sa longueur afin que les N utilisateurs connectés les plus récents y soient toujours stockés.
#Ajouter la personne actuellement connectée à la liste chaînée
ret=r.lpush("login:last_login_times",uid)
#Conserver la liste chaînée avec seulement N bits
ret=redis.ltrim("login: last_login_times",0 ,N-1)
De cette façon, vous devez obtenir l'identifiant de la dernière personne connectée, le code suivant suffit
last_login_list=r.lrange("login:last_login_times",0,N- 1)
De plus, trouvez celui avec le plus de temps de connexion Personnes, sortedset est très adapté aux besoins tels que le tri et les classements. Nous stockons les utilisateurs et les temps de connexion dans un ensemble trié.
zaddlogin:login_times51
zaddlogin:login_times12
zaddlogin:login_times23
De cette façon, si un utilisateur se connecte, un ensemble trié supplémentaire est maintenu, le code est le suivant
#Le nombre de connexions pour le l'utilisateur est augmenté de 1
ret=r .zincrby( "login:login_times",1,uid)
Alors, comment obtenir l'utilisateur avec le plus de temps de connexion ? Triez simplement le Nième utilisateur dans l'ordre inverse
ret=r.zrevrange(" login:login_times",0,N -1)
On peut voir que DEV doit ajouter 2 lignes de code, et DBA n'a pas besoin de prendre en compte les index ou quoi que ce soit.
Système TAG
Les balises sont particulièrement courantes dans les applications Internet si elles sont conçues avec une base de données relationnelle traditionnelle, elles seraient un peu indescriptibles. Prenons l'exemple de la recherche d'un livre pour voir les avantages de redis à cet égard.
Conception d'une base de données relationnelle
Deux tableaux, un pour les détails du livre et un pour les balises, indiquant les balises de chaque livre. Il y a plusieurs balises dans un livre.
mysql>select*frombook;
+----------------+---------------------- --+ ----------------+
|id|nom|auteur|
+------+----------- --- ------------------+----------------+
|1|TheRubyProgrammingLanguage|MarkPilgrim|
|1|Rubyonrail |DavidFlanagan|
|1|ProgrammationErlang|JoeArmstrong|
+------+------------------------ ------- ---+----------------+
mysql>select*fromtag;
+---------+- ------- -+
|tagname|book_id|
+---------+---------+
|rubis|1|
|rubis |2|
|web |2|
|erlang|3|
+---------+---------+
Si tu as un tel besoin, regarde pour les livres sur Ruby et sur le Web, que se passera-t-il s'il s'agit d'une base de données relationnelle ? .book_id=t2.book_idandb.id=t1 .book_id
La table de balises est automatiquement associée deux fois puis associée au livre. Ce SQL est encore relativement complexe. Et si l'exigence est Ruby, mais pas un livre Web ?
. En fait, les données relationnelles ne sont pas très adaptées à ces opérations ensemblistes.
Conception de REDIS
Tout d'abord, les données du livre doivent être stockées, comme ci-dessus.
Setbook:1:name"TheRubyProgrammingLanguage"
Setbook:2:name"Rubyonrail"
Setbook:3:name"ProgrammingErlang"
setbook:1:author"MarkPilgrim"
Setbook:2:author"David Flanagan "
Setbook:3:author"JoeArmstrong"
tag table Nous utilisons des ensembles pour stocker des données, car les ensembles sont efficaces pour trouver des intersections et des unions
sadtag: ruby1
Alors, quels sont les livres qui appartiennent à ruby mais appartiennent aussi au web ? inter_list=redis.sinter("tag.web","tag:ruby") C'est-à-dire les livres qui appartiennent à ruby mais pas au web ? inter_list= redis .sdiff("tag.ruby","tag:web") Une collection de livres appartenant à ruby et au web ? inter_list=redis.sunion("tag.ruby","tag:web" ) Simple Ce n'est pas possible. À partir des deux exemples ci-dessus, nous pouvons voir que dans certains scénarios, les bases de données relationnelles ne sont pas adaptées. Vous pourrez peut-être concevoir un système qui répond à vos besoins, mais cela semble toujours bizarre et a une sensation mécanique. Surtout dans l'exemple de la connexion au système, une indexation de l'entreprise est fréquemment créée. Dans un système complexe, ddl (créer un index) peut modifier le plan d'exécution. Étant donné que le SQL dans l'ancien système avec des activités complexes est très étrange, ce qui oblige d'autres SQL à utiliser des plans d'exécution différents, ce problème est difficile à prévoir. Il est trop difficile d'exiger que le DBA comprenne tout le code SQL de ce système. Ce problème est particulièrement grave dans Oracle, et tous les administrateurs de base de données l'ont probablement rencontré. Bien qu'il existe désormais des méthodes DDL en ligne, DDL n'est toujours pas très pratique pour des systèmes comme MySQL. Lorsqu'il s'agit de grandes tables, le DBA se lève tôt le matin pour opérer pendant les heures creuses, ce que je fais souvent. Il est très pratique d'utiliser Redis pour gérer cette demande et nécessite uniquement que l'administrateur de base de données estime la capacité.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!