Vorwort
Frühling fördert eine relativ leistungsstarke Vorlage, um die Verwendung von Redis leicht zu verwenden. Ich habe Redis zuvor im Frühlingsökosystem verwendet, aber direkt Jedis für entsprechende Wechselwirkungen verwendet. Schauen wir uns nun an, wie Redistemplate implementiert wird und ob es bequemer zu bedienen ist.
Jedis wird weiterhin für die Verwaltung des Verbindungspools verwendet. Zusätzlich zur Einführung von Spring-Data-Redis sowie Jedis-Abhängigkeiten fügen Sie die POM-Datei hinzu
<Depopentcy> <GroupId> org.springFramework.data </GroupId> <artifactId> Spring-data-redis </artifactId> <version> 1.8.4.Release </Version> </abhängig> <Epaptid> <gruppeId> REDIS.Clients </GroupID> <artifactid> Jedis </artifactid> <version> </artifactid> </artifactid> <version> </artifactid> </artifactid> <version> </artifactid> </artifactid> </0/0/artifactid>
Wenn Sie serialisierungsbezogene Parameter angeben müssen, können Sie auch Jackson einführen. Dieser Artikel ist einfach Einstiegsebene, sodass Sie dies nicht hinzufügen werden
Bereiten Sie die Konfigurationsparameter im Zusammenhang mit Redis vor. Zu den allgemeinen gehören Host, Port, Kennwort, Zeitüberschreitung .... Die folgende ist eine einfache Konfiguration und gibt die entsprechenden Bedeutungen an.
redis.hostname = 127.0.0.1redis.port = 6379Redis.Password = https: //blog.hhui.top# Verbindung Timeout redis.timeout = 10000#Maximale Leerlaufnummer redis.maxidle Wenn es sich um Jedis 2.4 handelt, verwenden Sie diese Eigenschaft auf redis.maxtotal = 1000#Maximale Verbindungseinrichtung Wartezeit. Wenn diese Zeit diesmal überschreitet, wird eine Ausnahme eingehen. Eingestellt auf -1 bedeutet keine Grenze. redis.maxwaitmillis = 1000#Die minimale Leerlaufzeit der Verbindung beträgt standardmäßig 18000000 ms (30 Minuten) redis.MineVictableableIdletImemMillis = 300000#Die maximale Anzahl von Verbindungen wird jedes Mal freigesetzt, Standard -3Redis. Standard -1Redis.
veranschaulichen
Bitte denken Sie daran, das Redis -Passwort festzulegen, insbesondere wenn Sie den Remote -Zugriff zulassen. Wenn Sie kein Passwort haben, wird die Standard -Portnummer leicht gescannt und in das Skript injiziert und dann mit dem Abbau für Personen (persönliche Erfahrung ...) beginnt
Gemäß der allgemeinen Idee müssen Sie zunächst die obige Konfiguration laden, einen Redis -Verbindungspool erstellen, dann das Redistemplate -Objekt instanziieren und schließlich diese Stärke halten, um verschiedene Lese- und Schreibvorgänge zu starten
Verwenden Sie Javaconfig, um, hauptsächlich zwei Bohnen, die Konfigurationsdatei zu konfigurieren, um verschiedene Parameter festzulegen, und die erwartete Redistemplate
@Configuration @PropertySource ("ClassPath: redis.Properties") öffentliche Klasse REDISCONFIG erweitert JCACHECONFIGURERSUPPORT {@autowired Private Environment Umgebung; @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")); fak.settimeout (Integer.ParseInt (Environment.getProperty ("redis.timeout"))); fak.getpoolConfig (). setMaxidle (Integer.ParseInt (Environment.getProperty ("redis.maxidle"))); fac.getPoolConfig (). setMaxtotal (Integer.ParseInt (Environment.getProperty ("redis.maxtotal")); fak.getpoolconfig (). setMaxwaitmillis (Integer.ParseInt (Environment.getProperty ("redis.maxwaitmillis"))); fac.getPoolConfig (). setMineVictableIdletImemillis (Integer.ParseInt (Environment.getProperty ("redis.MinevictableIdletImemillis"))); fak.getpoolconfig (). setMinevictableIdletImemillis "))); fac.getpoolconfig (). .SetNumTestSperevictionRun (Integer.ParseInt (Environment.getProperty ("redis.numTestSperevictionRun")); fak.getPoolconfig (). redistemplate (redisconnectionFactory redisconnectionFactory) {redistemplate <String, String> redis = new redistemplate <> (); @Runwith (SpringJunit4ClassRunner.class) @ContextConfiguration (classes = {redisconfig.class}) public class redistestest {@autowired private redistemplate <string, string> redistemplate; @Test public void testredisobj () {map <string, Objekt> Eigenschaften = new HashMap <> (); Eigenschaften.put ("123", "Hallo"); Eigenschaften.put ("ABC", 456); redistemplate.opsforhash (). putall ("Hash", Eigenschaften); MAP <Objekt, Objekt> Ans = redistemplate.opsforhash (). Einträge ("Hash"); System.out.println ("Ans:" + Ans); }}Nach der Ausführung ist die Ausgabe wie folgt
Ans: {123 = Hallo, ABC = 456}Nach der obigen Konfiguration und Implementierung zu urteilen, ist dies sehr einfach. Es gibt im Grunde keinen Kreis um
127.0.0.1:6379> Get Hash (NIL) 127.0.0.1:6379> Schlüssel *1) "/xac/xed/x00/x05T/x00/x04HASH"
Es gibt kein Problem mit der Verwendung des Code, um ihn zu überprüfen. Ich habe die Konsole direkt angeschlossen und festgestellt, dass sich dieser Schlüssel von dem unterscheidet, was wir erwartet haben, mit einigen Präfixen, warum?
Um das obige Problem zu lösen, kann ich es nur debuggen und sehen, was es verursacht hat.
Der entsprechende Quellcode -Standort:
// org.springframework.data.redis.core.abstractoperations#RawKeyByte [] Rawkey (Objektschlüssel) {assert.notnull (Schlüssel, Non -Null -Schlüssel erforderlich "); zurückgeben. (Byte []) ((Byte []) Schlüssel: this.keyserializer (). Serialize (Schlüssel);}Sie können sehen, dass dieser Schlüssel nicht der Schlüssel ist. Das Ergebnis des Debuggens ist, dass der Standard -Serializer JdkserializationReDisSerializer ist.
Folgen Sie dann den Hinweisen und gehen Sie Schritt für Schritt tiefer, der Link lautet wie folgt
// org.springframework.core.serializer.serializingConverter#convert// org.springframework.core.serializer.DefaultSerializer#serializepublic class DefaultSerializer implements Serializer<Object> { public DefaultSerializer() { } public void serialize(Object object, OutputStream outputStream) throws IOException {if (! (Objektinstanz von serialisierbar)) {Neue IllegalArgumentException (this.getClass (). GetImpleName () + "Erfordert eine serialisierbare Nutzlast, aber ein Objekt von Typ [" + Object.getClass (). getName () + "]"); } else {ObjectOutputStream ObjectOutputStream = new ObjectOutputStream (outputStream); ObjectOutputStream.writeObject (Objekt); ObjectOutputStream.flush (); }}}Die spezifische Implementierung ist also sehr klar, was ObjektOutputStream ist. Dieses Ding ist das primitivste serialisierte Deserial -Streaming -Tool in Java. Es enthält Typinformationen, sodass es mit dem Präfix ausgestattet ist.
Um dieses Problem zu lösen, ist es klarer. Ersetzen Sie den nativen JDKSerializationReTisserializer und ändern Sie ihn in die Zeichenfolge, die nur einen StringRedisserializer bietet. An der Konfiguration von redistemplate ändern Sie ihn daher geringfügig ändern
@BeanPublic redistemplate <String, String> redistemplate (redisconnectionFactory redisconnectionFactory) {redistemplate <string, string> redis = new redItemplate <> (); redis.setConnectionFactory (RedisconnectionFactory); // Setzen Sie die Standard -Serialisierungsmethode von Redis String/Value StringRedisserializer StringRedisserializer = new StringRedisserializer (); redis.setkeyserializer (StringRedisserializer); redis.setValueSerializer (StringRedisserializer); redis.sethashkeyserializer (StringRedisserializer); redis.sethashValueSerializer (StringRedisserializer); redis.afterPropertiesset (); return Redis;}Wieder ausführen und das peinliche Ding passierte, die Ausnahme wurde ausgelöst und die Typumwandlung fehl
java.lang.classcastexception: java.lang.Ineger kann nicht an java.lang.string unter org.springframework.data.redis.serializer.stringRedisserializer.Serialize (StringRedisserializer.java:33) bei org.springframework.data.redis.core.abstractoperations.rawhashValue (Abstractoperations.java:171) unter org.springframework.data.redis.core.defaulthoperations.putall (Defaultallhashoperations.java:129) ...
Wenn man sich den vorherigen Testfall ansieht, hat der Wert in der Karte Ganzzahl und der von StringRedisserializer empfangene Parameter muss eine Zeichenfolge sein. Verwenden Sie dies also nicht, und Sie werden immer noch eine kompatible schreiben.
public class defaultStreserializer implementiert recisSerializer <Object> {private endgültige charset charset; public defaultStrSerializer () {this (charset.Forname ("utf8")); } public defaultStrSerializer (charSet charSet) {assert.notnull (charset, "charset darf nicht null sein!"); this.charSet = charSet; } @Override public byte [] serialize (Objekt O) löst SerializationException {return o == null aus? null: string.Valueof (o) .getBytes (charset); } @Override öffentliches Objekt Deserialize (byte [] bytes) löst SerializationException aus {return bytes == null? NULL: Neue Zeichenfolge (Bytes, Charset); }}Dann können Sie nach der Ausführung Spaß haben und testen
Tasten *1) "/xac/xed/x00/x05T/x00/x04HASH" 2) "Hash" 127.0.0.1:6379> HGetALL Hash1) "123" 2) "Hallo" 3) "Abc" 4) "456"
Sehen wir kurz die Verwendungshaltung von Redistemplate und lesen und umfassen die von Opsforxxx für verschiedene Datenstrukturen verwendete Aufrufmethode (String, List, Zset, Hash).
// Hash -Datenstrukturoperation org.springframework.data.redis.core.redistemplate#opsforhash // listorg.springframework.data.redis.core.redistemplate#opsforlist // Stringorg.springframework.data.redis.core.core.redistemplatte######################### setorg.springframework.data.redis.core.redistemplate#opsforzset
Zusätzlich zur oben genannten Verwendungsmethode besteht eine andere gemeinsame Verwendung darin, die Ausführung direkt zu verwenden. Ein einfacher Fall ist wie folgt
@Testpublic void testredis () {String key = "Hallo"; String value = "World"; redistemplate.execute ((reciscallback <void>) con -> {con.set (key.getBytes (), value.getBytes ()); return null;}); String asn = redISTemplate.execute (((reciscallback <string>) con -> neuer String (con.get (key.getBytes ()))); System.out.println (ASN); String hkey = "hKey"; redistemplate.execute ((reciscallback <void>) con -> {con.hset (hkey.getBytes (), "23" .getBytes (), "Was" .GetBytes ()); return null;}); Map <byte [], byte []> map = redistemplate.execute ((reciscallback <map <byte [], byte []>) con -> con.hgetall (hkey.getBytes ())); für (map.entry <byte [], byte [] >> Eintrag: map.entrySet ()) {System.out.println ("Schlüssel:" + neue String (Eintrag.Getkey ()) + "Wert:" + neuer String (Eintrag.getValue ()); }}Das Ausgangsergebnis ist wie folgt
Welt
Schlüssel: 23 | Wert: Was
Eine Frage, an die natürlich gedacht werden kann, ist der Unterschied zwischen den beiden oben genannten Methoden.
Die zugrunde liegende Schicht von Opsforxxx erfolgt durch Aufrufen von Execute. Es fasst hauptsächlich einige Verwendungshaltungen zusammen und definiert die Serialisierung, wodurch es einfacher und bequemer zu bedienen ist. Auf diese Weise ist die kleine Trompete, dass sie jedes Mal ein neues Standard -Objekt für defaultxxxoperations erstellen muss und es noch einen Schritt macht. Wird es basierend darauf zusätzliche Leistung und Speicheraufwand bringen? Ich habe es nicht getestet, aber ich persönlich habe das Gefühl, dass die Menge klein ist, es sollte keine offensichtlichen Auswirkungen haben. Und wenn das QPS sehr hoch ist, ist die Hilfe, die diese bequeme Optimierung bringen kann, wahrscheinlich nicht viel.
Studie-Demo/Spring-Redis
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.