序文
Springは、Redisの使用に簡単に使用できる比較的強力なテンプレートをカプセル化します。以前は春のエコシステムでRedisを使用しましたが、対応する相互作用にJedisを直接使用しました。次に、Redistemplateがどのように実装されているか、使用する方が便利かどうかを見てみましょう。
Jedisは引き続き接続プール管理に使用されているため、Spring-Data-RedisとJedis依存関係を導入することに加えて、POMファイルを追加します
<Dependency> groupId> org.springframework.data </groupid> <artifactid> spring-data-redis </artifactid> <バージョン> 1.8.4. release </version> </dependency> <seplency> redis.clients </groupid> </groupidid> jedis </artifactid> </</</</</</</</</</</</birgnes
シリアル化関連のパラメーターを指定する必要がある場合は、ジャクソンを紹介することもできます。この記事は簡単なエントリーレベルなので、これを追加しません
Redis関連の構成パラメーターを準備します。一般的なパラメーターには、ホスト、ポート、パスワード、タイムアウトが含まれます。以下は簡単な構成であり、対応する意味を示します。
Redis.hostname = 127.0.0.1redis.port = 6379Redis.password = https://blog.hhui.top#接続タイムアウトredis.timeout = 10000#最大アイドル番号redis.maxidle = 300#コントロールJedis 2.4の場合は、このプロパティを使用してredis.maxtotal = 1000#最大接続の確立待機時間を取得します。この時間がこの時間を超えた場合、例外が受信されます。 -1に設定すると、制限はありません。 Redis.maxwaitmillis = 1000#接続の最小アイドル時間はデフォルトです18000000ms(30分)redis.minevictableidletimemillis = 300000#最大数の接続数は毎回リリースされます。デフォルト-1Redis.TimeBetWeenEvictionRunsMillis = 30000#プールから接続を削除する前に確認するかどうか、検証が失敗した場合は、プールから接続を削除し、別のRedis.testonborrow = true#IDLE、Default falsedis.testhileidle = true
説明します
特にリモートアクセスを許可する場合は、Redisパスワードを設定することを忘れないでください。パスワードがない場合、デフォルトのポート番号は簡単にスキャンされてスクリプトに注入され、人のマイニングを開始します(個人的な経験...)
一般的なアイデアによると、最初に、上記の構成をロードし、Redis接続プールを作成し、Redistemplateオブジェクトをインスタンス化し、最後にこの強度を保持して、さまざまな読み取り操作を開始する必要があります。
javaconfigを使用して、主に2つの豆を構成し、構成ファイルを読み取り、さまざまなパラメーターを設定し、予想されるredistemplateを設定します
@configuration @propertySource( "classpath:redis.properties")public class redisconfigはjcacheconfigurersupport {@autowiredプライベート環境環境を拡張します。 @Bean Public RedisconnectionFactory RedisconnectionFactory(){jedisconnectionFactory fac = new JedisconnectionFactory(); FAC.SETHOSTNAME(Environment.GetProperty( "Redis.Hostname")); fac.setport(integer.parseint(Environment.getProperty( "redis.port"))); fac.setPassWord(環境.getProperty( "redis.password")); fac.settimeout(integer.parseint(Environment.getProperty( "redis.timeout"))); fac.getpoolconfig()。setMaxidle(integer.parseint(entuminer.getProperty( "redis.maxidle"))); fac.getpoolconfig()。setmaxtotal(integer.parseint(entuminer.getProperty( "redis.maxtotal"))); fac.getPoolConfig()。setMaxWaitMillis(integer.parseint(entumine.getProperty( "redis.maxwaitmillis"))); fac.getpoolconfig()。setMinevictableIdletimemillis(integer.parseint(entumine.getProperty( "redis.minevictableidletimemillis"))); fac.getpoolconfig()。setMinevictableIdletimemillis "))))))))。 .setnumtestsperevictionrun(integer.parseint(entumine.getProperty( "redis.numtestsperevictionrun")); fac.getpoolconfig()。 string> redisconectionfactory redistemplate <string> redistemplate <>();@runwith(springjunit4classrunner.class)@contextconfiguration(classes = {redisconfig.class})public class redistest {@autowired private redistemplate <string、string> redistemplate; @test public void testredisobj(){map <string、object> properties = new hashmap <>(); properties.put( "123"、 "hello"); Properties.put( "ABC"、456); redistemplate.opsforhash()。putall( "hash"、Properties); map <object、object> ans = redistemplate.opsforhash()。エントリ( "hash"); System.out.println( "ans:" + ans); }}実行後、出力は次のとおりです
Ans:{123 = hello、abc = 456}上記の構成と実装から判断すると、非常に簡単です。基本的に円はありませんが、Redis-Cliに接続すると、ハッシュキーのコンテンツを照会することはできません
127.0.0.1:6379>ハッシュ(nil)127.0.0.1:6379> keys *1) "/xac/xed/x00/x05t/x00/x04hash"
コードを使用してチェックアウトするのに問題はありません。コンソールを直接接続して、このキーが予想されたものとは異なることがわかりました。
上記の問題を解決するために、私はそれをデバッグして、何が原因であるかを見ることができます。
対応するソースコードの場所:
// org.springframework.data.redis.core.abstractoperations#rawkeybyte [] rawkey(object key){assert.notnull(key、 "non null key required"); this.keyserializer()== null && key instance of byte []を返しますか? (byte [])((byte [])key):this.keyserializer()。serialize(key);}このキーはkey.getBytes()ではないことがわかりますが、this.keyserializer()。serialize(key)が呼び出されます。デバッグの結果、デフォルトのシリアルはjdkserializededisserializerです。
次に、手がかりに従って、より深い段階的に進み、リンクは次のとおりです
// org.springframework.core.serializer.serializingconverter#convert // org.springframework.core.serializer.defaultsearializer {if(!(!(!)serializable)){新しいIllegalArgumentException(this.getClass()。getSimplename() + "をスローします。 } else {objectOutputStream objectOutmoutputStream = new objectOutputStream(outputStream); ObjectOutputStream.WriteObject(object); ObjectOutputStream.Flush(); }}}したがって、特定の実装は非常に明確であり、ObjectOutputStreamです。このことは、Javaで最も原始的なシリアル化された脱上上のストリーミングツールです。タイプ情報が含まれているため、プレフィックスが装備されます。
したがって、この問題を解決するために、それはより明確です。ネイティブのJDkserializedRedisserializerを交換し、それを文字列に変更します。これは、StringRedisserializerを提供するだけであるため、Redistemplateの構成では、わずかに変更します。
@beanpublic redistemplate <string、string> redistemplate(redisconnectionfactory redisconnectionFactory){redistemplate <string、string> redis = new redistemplate <>(); redis.setConnectionFactory(RedisconnectionFactory); // redis string/value stringredisserializer stringredisserializer = new StringRediserializer()のデフォルトのシリアル化方法を設定します。 redis.setkeyserializer(stringredisserializer); redis.setValueserializer(StringRedisserializer); redis.sethashkeyserializer(stringredisserializer); Redis.SethashValueserializer(StringRedisserializer); redis.afterpropertiesset(); Redisを返します;}もう一度実行すると、恥ずかしいことが起こり、例外がスローされ、タイプの変換が失敗しました
java.lang.classcastexception:java.lang.integerは、org.springframework.data.redis.serializer.stringredisserializer.serialize(stringrediserializer.java:33)でorg.springframework.data.redis.serializer.stringredisserializerでjava.lang.stringにキャストすることはできません。 org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:171) at org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:129) ...
前のテストケースを見ると、マップ内の値には整数があり、StringRedisserializerが受信したパラメーターは文字列でなければならないため、これを使用しないでください。
Public Class DefaultStrserializerは、Redisserializer <Object> {プライベートファイナルチャーセットチャーセットを実装しています。 public defaultStrserializer(){this(charset.forname( "utf8")); } public DefaultStrserializer(charset charset){assert.notnull(charset、 "charsetはnull!"); this.charset = charset; } @override public byte [] serialize(object o)throws serializationexception {return o == null? null:string.valueof(o).getBytes(charset); } @OverrideパブリックオブジェクトDeserialize(byte [] bytes)throws serializationexception {return bytes == null? null:new String(bytes、charset); }}その後、実行後に楽しんでテストすることができます
keys *1) "/xac/xed/x00/x05t/x00/x04hash" 2) "hash" 127.0.0.1:6379> hgetall hash1) "123" 2) "hello" 3) "abc 4)" 456 "
Redistemplateの使用姿勢を簡単に確認し、異なるデータ構造(String、List、Zset、Hash)でOpsForxxxが使用する呼び出し方式を読み取り、カプセル化します。
//ハッシュデータ構造操作org.springframework.data.redis.core.redistemplate#opsforhash // listorg.springframework.data.redis.core.redistemplate#opsforlist // stringorg.springframework.data.redis.core。 setorg.springframework.data.redis.core.redistemplate#opsforzset
上記の使用法に加えて、もう1つの一般的な方法は、実行を直接使用することです。簡単なケースは次のとおりです
@testpublic void testredis(){string key = "hello";文字列値= "world"; redistemplate.execute((rediscallback <void>)con-> {con.set(key.getBytes()、value.getBytes()); return null;}); string asn = redistemplate.execute((rediscallback <string>)con-> new String(con.get(key.getBytes()))); System.out.println(asn);文字列hkey = "hkey"; redistemplate.execute((rediscallback <void>)con-> {con.hset(hkey.getBytes()、 "23" .getBytes()、 "what" .getBytes()); return null;}); map <byte []、byte []> map = redistemplate.execute((rediscallback <map <byte []、byte []>)con-> con.hgetall(hkey.getBytes())); for(map.entry <byte []、byte [] >> entry:map.entryset()){system.out.println( "key:" + new String()) + "| value:" + new String(entry.getValue())); }}出力の結果は次のとおりです
世界
キー:23 |価値:何
自然に考えることができる質問は、上記の2つの方法の違いは何ですか?
OpsForxxxの基礎となる層は、executeを呼び出すことによって行われます。主にいくつかの使用姿勢をカプセル化し、シリアル化を定義するため、使用がより簡単で便利になります。このようにして、小さなトランペットは、毎回新しいDefaultXXXoperationsオブジェクトを作成する必要があることであり、もう1つのステップが必要です。これに基づいて、追加のパフォーマンスとメモリオーバーヘッドをもたらしますか?私はそれをテストしていませんが、個人的には量が少ないと感じています。明らかな影響はないはずです。そして、QPSが非常に高い場合、この便利な最適化がもたらすことができる助けはおそらくそうではありません。
Study-demo/spring-redis
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。