Préface
Le printemps résume un modèle relativement puissant pour une utilisation facile dans l'utilisation de Redis; J'ai déjà utilisé Redis dans l'écosystème de printemps, mais j'ai utilisé directement les Jedis pour les interactions correspondantes. Jetons maintenant un coup d'œil à la mise en œuvre de Redemplate et si elle est plus pratique à utiliser.
Les Jedis sont toujours utilisés pour la gestion du pool de connexions, donc en plus d'introduire le printemps-data-redis, ainsi que les dépendances Jedis, ajoutez le fichier POM
<dependency> <proupId> org.springframework.data </rom grouped> <artifactId> printemps-data-redis </ artifactid> <version> 1.8.4.release </ version> </ Dependency> <Dedency> <proupId> redis.clients </proupId> <e Artifactid> jedis </tatifatid> <Dursef
Si vous devez spécifier des paramètres liés à la sérialisation, vous pouvez également introduire Jackson. Cet article est simple d'entrée de gamme, donc vous ne l'ajoute pas
Préparer les paramètres de configuration liés à Redis, les paramètres communs incluent l'hôte, le port, le mot de passe, le délai d'attente .... Ce qui suit est une configuration simple et donne les significations correspondantes.
redis.hostname = 127.0.0.1redis.port = 6379redis.password = https: //blog.hhui.top# Connection Timeout redis.timeout = 10000 # Numéro de ralenti maximum redis.maxidle = 300 # Contrôles combien de jedis peuvent être inoffés à un pool pour remplacer le redis ci-dessus. S'il s'agit de Jedis 2.4, utilisez cette propriété pour redis.mextsotal = 1000 # temps d'attente d'établissement de connexion maximale. Si ce temps dépasse cette fois, une exception sera reçue. Réglé sur -1 signifie aucune limite. redis.maxwaitmillis = 1000 # Le temps d'inactivité minimum de la connexion est par défaut 18000000 ms (30 minutes) redis.MINEVICTABLEIDLEMEMILLIS = 300000 # Le nombre maximum de connexions est publié à chaque fois, par défaut 3redis.numtestSperevictionRun = 1024 # L'intervalle de temps pour évoluer (MS) Si c'est négatif, le fil d'évaluation ne fait pas. Par défaut -1redis.timebetweenvictionRunsmillis = 30000 # Si vous devez vérifier avant de supprimer la connexion du pool, si la vérification échoue, supprimez la connexion du pool et essayez de supprimer un autre redis.testonborrow = true # Vérification de la validité quand inacie
illustrer
N'oubliez pas de définir le mot de passe Redis, en particulier lorsque vous autorisez l'accès à distance. Si vous n'avez pas de mot de passe, le numéro de port par défaut sera facilement numérisé et injecté dans le script, puis commencera à miner des personnes (expérience personnelle ...)
Selon l'idée générale, vous devez d'abord charger la configuration ci-dessus, créer un pool de connexion Redis, puis instancier l'objet Reistemplate et enfin tenir cette force pour démarrer diverses opérations de lecture et d'écriture
Utilisez JavaconFig pour configurer, principalement deux haricots, lisez le fichier de configuration pour définir divers paramètres et le reistemplate attendu
@ Configuration @ propriétéSource ("classPath: redis.properties") La classe publique RedisConfig étend JcacheConfigurersupport {@autowired Environment privé environnement; @Bean public redisconnectionfactory redisconnectionfactory () {JedisconnectionFactory fac = new JedisconnectionFactory (); fac.sethostname (Environment.getProperty ("redis.hostname")); fac.setport (Integer.ParseInt (Environment.getProperty ("redis.port"))); fac.setpassword (Environment.getProperty ("redis.password")); fac.settimeout (Integer.ParseInt (Environment.getProperty ("redis.timeout"))); fac.getpoolconfig (). setMaxidle (Integer.ParseInt (Environment.GetProperty ("redis.maxidle"))); fac.getpoolconfig (). setMextotal (Integer.ParseInt (Environment.getProperty ("redis.mextotal"))); fac.getpoolconfig (). SetMaxWaitMillis (Integer.ParseInt (Environment.getProperty ("redis.maxwaitmilis"))); fac.getpoolconfig (). SetMineVictableIdleMemillis (Integer.Parseint (Environment.getProperty ("redis.MinevictableIdleMemillis"))); fac.getpoolconfig (). setMineVictableIdleMemillis "))); fac.getpoolconfig (). SetMineVictableIdleMemillis (Integer.Parseint (Environment.getProperty (" redis.MinevictableIdleMemillis "))); FAC.GetPoolConfig () .SetNumTestSperevictionRun (Integer.Parseint (Environment.getProperty ("redis.numtestSperevictionrun")); fac.getpoolconfig (). SettestonBorrow (boolean.parseboolean (Environment.getProperty (redis.testonborrow ")); Redistemplate (RedisconnectionFactory redéconnection @Runwith (SpringJunit4ClassRunner.class) @ContextConfiguration (Classes = {re-onConfig.class}) Public Class RedestTest {@autowired private reistetemplate <String, String> Redemplate; @Test public void testRedisObj () {map <string, object> properties = new hashmap <> (); Properties.put ("123", "Bonjour"); Properties.put ("ABC", 456); reidemplate.opsforhash (). putall ("hash", propriétés); Map <object, objet> ans = reidemplate.opsforhash (). Entrées ("hash"); System.out.println ("Ans:" + Ans); }}Après l'exécution, la sortie est la suivante
ANS: {123 = Bonjour, ABC = 456}À en juger par la configuration et l'implémentation ci-dessus, c'est très simple. Il n'y a essentiellement pas de cercle autour, mais lorsque vous le connectez avec Redis-Cli, vous ne pouvez pas interroger le contenu de la clé de hachage
127.0.0.1:6379> Get Hash (nil) 127.0.0.1:6379> Keys * 1) "/ xac / xed / x00 / x05t / x00 / x04hash"
Il n'y a aucun problème à utiliser le code pour le vérifier. J'ai directement connecté la console et j'ai constaté que cette clé est différente de ce à quoi nous nous attendions, avec certains préfixes, pourquoi?
Afin de résoudre le problème ci-dessus, je ne peux que le déboguer et voir ce qui l'a causé.
Emplacement du code source correspondant:
// org.springframework.data.redis.core.abstractoperations # RawKeyByte [] RawKey (clé d'objet) {assert.notnull (clé, "clé non nul requise"); return this.KeySerializer () == null && key instanceof octet []? (octet []) ((byte []) key): this.KeySerializer (). serialize (key);}Vous pouvez voir que cette clé n'est pas la clé.getBytes () à ce que nous attendions, mais ce.KeySerializer (). Serialize (clé) est appelé. Le résultat du débogage est que le sérialiseur par défaut est JDKSerializationDisserializer.
Ensuite, suivez les indices et allez plus loin étape par étape, le lien est le suivant
// org.springframework.core.serializer.serializingConverter # convert // org.springframework.core.serializer.defaultserializer # serializepublic classageSerializer implémente le sérialiseur <objet> {public DéfautelSerializer () {} public Vee Serialize (Object Object, OutputStream (! (objet instanceof serialisable)) {lancez new illégalArgumentException (this.getClass (). getIMPlename () + "nécessite une charge utile sérialisable mais a reçu un objet de type [" + object.getClass (). getName () + "]"); } else {objectOutStream objectOutStStream = new ObjectOutputStream (outputStream); objectOutputStream.WriteObject (objet); objectOutputStream.flush (); }}}La mise en œuvre spécifique est donc très claire, qui est objectOutputStream. Cette chose est l'outil de streaming désérial sérialisé le plus primitif de Java. Il contiendra des informations de type, il sera donc équipé du préfixe.
Donc, pour résoudre ce problème, c'est plus clair. Remplacez le jdkserializationdisserializer natif et passez-le en chaîne, qui fournit juste un stringRedisserializer, donc à la configuration de Redemplate, modifiez-le légèrement
@BeanPublic Redistetemplate <String, String> Redistetemplate (redisconnectionfactory redisconnectionfactory) {redemplate <string, string> redis = new Redetemplate <> (); redis.setConnectionFactory (redéconnectionfactory); // Définissez la méthode de sérialisation par défaut de redis string / valeur stringRedisSerializer stringRedisSerializer = new StringRedisSerializer (); redis.setKeySerializer (stringRedisserializer); redis.setValueLeSerializer (stringRedisSerializer); redis.sethashkeyserializer (stringredisserializer); redis.sethAshValueSerializer (stringRedisserializer); redis.afterpropertiesset (); retour redis;}Exécuter à nouveau et la chose embarrassante s'est produite, l'exception a été lancée et la conversion de type a échoué
java.lang.classCastException: java.lang.integer ne peut pas être jeté sur java.lang.string sur org.springframework.data.redis.serializer.stringredisserializer.serialize (stringredisserializer.java:33) à la org.springframework.data.redis.core.abstractoperations.rawhashvalue (abstractoperations.java:171) à org.springframework.data.redis.core.defaulthashoperations.putall (Defaulthashoperations.java:129) ...
En regardant le cas de test précédent, la valeur de la carte a un entier, et le paramètre reçu par StringRedisSerializer doit être une chaîne, donc ne l'utilisez pas, et vous en écrirez toujours un compatible.
Classe publique DefaultStrserializer implémente le redéaliseur <objet> {private final Charset Charset; public defaultstrSerializer () {this (charset.forname ("utf8")); } public DefaultstrSerializer (Charset Charset) {ASSERT.NOTNULL (Charset, "Charset ne doit pas être nul!"); this.charset = charset; } @Override public octet [] serialize (objet o) lève SerializationException {return o == null? null: string.valueof (o) .getBytes (charset); } @Override Objet public Desérialize (octet [] octets) lève SerializationException {return bytes == null? null: new String (octets, charse); }}Ensuite, vous pouvez commencer à vous amuser et à tester après l'exécution
Keys * 1) "/ xac / xed / x00 / x05t / x00 / x04hash" 2) "hash" 127.0.0.1:6379> hgetall hash1) "123" 2) "Bonjour" 3) "ABC" 4) "456"
Voyons brièvement la posture d'utilisation de ReDistemplate et lisons et encapsulez la méthode d'appel utilisée par Opsforxxx pour différentes structures de données (String, List, Zset, Hash).
// Opération de structure de données de hachage org.springframework.data.redis.core.redistemplate # opsforhash // listorg.springframework.data.redis.core.data.redis.core.redistemplate # opsforvalue // setorg.springframework.data.redis.core.redistemplate # opsforzset
En plus de la méthode d'utilisation ci-dessus, un autre courant consiste à utiliser directement l'exécution. Un cas simple est le suivant
@TestPublic void testRedis () {String key = "Hello"; String Value = "World"; redesttemplate.execute ((redécallback <void>) con -> {con.set (key.getBytes (), value.getBytes ()); return null;}); String asn = redestEemplate.execute ((rediscallback <string>) con -> new String (con.get (key.getBytes ()))); System.out.println (ASN); String hkey = "hkey"; Redistetemplate.Exécute ((redécallback <void>) con -> {con.hset (hkey.getBytes (), "23" .getBytes (), "quoi" .getBytes ()); return null;}); Map <byte [], byte []> map = redestemplate.execute ((rediscallback <map <byte [], byte []>) con -> con.hgetall (hkey.getBytes ())); for (map.entry <byte [], byte [] >> entrée: map.entryset ()) {System.out.println ("key:" + new String (Entry.getKey ()) + "| value:" + new String (entry.getValue ()))); }}Le résultat de sortie est le suivant
monde
Clé: 23 | valeur: quoi
Une question qui peut être pensée naturellement est quelle est la différence entre les deux méthodes ci-dessus?
La couche sous-jacente d'Opsforxxx est effectuée en appelant EXECUTE. Il résume principalement certaines postures d'utilisation et définit la sérialisation, ce qui le rend plus facile et plus pratique à utiliser. De cette façon, la petite trompette est qu'elle doit créer un nouvel objet par défautxxxOperations à chaque fois, et cela fait un pas de plus. Sur la base de cela, apportera-t-il des performances et des frais généraux supplémentaires? Je ne l'ai pas testé, mais je pense personnellement que le montant est faible, il ne devrait pas y avoir d'impact évident; Et lorsque le QPS est très élevé, l'aide que cette optimisation pratique peut apporter n'est probablement pas beaucoup.
étude-démo / printemps-redis
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.