0121 spring-boot-redisの使用
19663 ワード
redisって何ですか?redisは、NoSQLの一種で、インターネット時代にシステムを加速させる役割を果たした.
redisはメモリデータベースで、7種類のデータ型のストレージをサポートし、性能は1 S 10 w回の読み書きをサポートする.redisが提供する簡単なトランザクションは、高同時シーンの下数の一貫性を保証します.redisは2.6バージョンの後にluaサポートを追加し、コマンドは原子的である.
この文章は主にspringbootのredis-starterに基づいている.HELLO、性能利器Redis.
spring-boot-starter-redis
これはspringbootが提供するredis操作ツールパッケージで、最下位のredis駆動はjedisではなくlettusを使用しています.
に頼る
シーケンス化
主にRedisTemplateによってredisを操作する.
もちろん、効率の高いkytoシーケンスなどのカスタムシーケンス化もサポートされています.StringRedisTemplate:key,valueは文字列に従って格納されます.TypedTupleはコレクション内の秩序要素を保存します.StringRedisTemplateのソースコードを確認できます.
データ型操作インタフェース
機能
単一操作インタフェース
バッチ操作インタフェース
ちくじしゅうごう
ZSetOperations
BoundZsetOperations
文字列
ValueOperations
BoundValueOpetations
しゅうごう
SetOperations
BoundSetOperations
リスト#リスト#
ListOperations
BoundListOperations
ハッシュ#ハッシュ#
HashOperations
BoundHashOperations
きすう
HyperLogLogOperations
BoundHyperLogLogOperaions
地理的位置
GeoOperations
BoundGeoOperations
コードの使用
同じ接続で複数回実行 SessionCallbackアドバンスドオペレータ RedisCallback低レベルオペランドコードで直接使用されるjava 8のlambda式.
コードの使用
文字列アクション
最もよく使われるデータ型は実際にはあまり使われていませんが、現実のシーンでは、1つのオブジェクトやオブジェクトのリストを文字列に変換して記憶し、取り出すときにオブジェクトに変換するのが一般的です.
コード:
その他の方法:
より多くの方法をビジネスシーンで使用する必要があります
リストアクション
コレクションアクション
秩序化された集合アクション
ハッシュ・アクション
Springbootにおけるredisの構成
構成は2つの部分に分けられ、接続プールと接続情報;次の表に、必要な構成を示します.
注記操作redis
CacheManager springを設定します.redis.cache.type=redis spring.redis.cache.name=redisCache
注記@EnableCachingで有効CachePut更新キャッシュ@CacheEvenicatクリアキャッシュ@CacheAbleクエリーキャッシュを使用
キャッシュは1つのクラスで相互に呼び出されて失効します:AOPに基づく動的エージェントは、エージェントクラスを生成していません;
使用法
redisの特殊な使い方
redisでのトランザクションの使用方法
SessionCallbackのRedisOperationsのwatch-multi-execループ操作を利用している.watch:いくつかのkeyを監視する;Multi:トランザクションを開始します.exec:実行トランザクションwatchのkeyに対応する値が変化した場合(元の値に設定しても変化した場合)、トランザクションはロールバックされます.そうでなければ、正常にトランザクションを実行します.redisはトランザクションを実行するとき、すべて実行するか、すべて失敗し、他のredisクライアントに中断されず、redisトランザクションの下でデータの一貫性を保証します.
一括実行redis操作
redisTemplate.executePipelined();
メッセージキュー
RedisMessageListenerContainerを定義し、topicとListenerを構成する必要があります.消費者としてredisTemplate.convertAndSendメソッドはメッセージを送信します.
Listenerの定義
Listenerコンテナの登録
テストコード redisTemplate.convertAndSend(channel,message);
luaスクリプトの使用
使用するredisTemplate.execute(RedisScript,List,List);
小結
この記事では、次のことを学ぶことができます.学会spring-boot-redis-starterを使用して各種データ型の操作を熟練している. は注釈を使用する方法でredisキャッシュを使用することを学んだ. redisの特殊な使い方、トランザクション、メッセージキュー、一括操作、luaスクリプトサポート;
コードポイントを取得します!
美人はやはり見せなければならない.
オリジナルは容易ではありません.転載は出典を明記してください.
redisはメモリデータベースで、7種類のデータ型のストレージをサポートし、性能は1 S 10 w回の読み書きをサポートする.redisが提供する簡単なトランザクションは、高同時シーンの下数の一貫性を保証します.redisは2.6バージョンの後にluaサポートを追加し、コマンドは原子的である.
この文章は主にspringbootのredis-starterに基づいている.HELLO、性能利器Redis.
spring-boot-starter-redis
これはspringbootが提供するredis操作ツールパッケージで、最下位のredis駆動はjedisではなくlettusを使用しています.
に頼る
org.springframework.boot
spring-boot-starter-data-redis
シーケンス化
主にRedisTemplateによってredisを操作する.
もちろん、効率の高いkytoシーケンスなどのカスタムシーケンス化もサポートされています.StringRedisTemplate:key,valueは文字列に従って格納されます.TypedTupleはコレクション内の秩序要素を保存します.StringRedisTemplateのソースコードを確認できます.
public StringRedisTemplate() {
setKeySerializer(RedisSerializer.string());
setValueSerializer(RedisSerializer.string());
setHashKeySerializer(RedisSerializer.string());
setHashValueSerializer(RedisSerializer.string());
}
データ型操作インタフェース
機能
単一操作インタフェース
バッチ操作インタフェース
ちくじしゅうごう
ZSetOperations
BoundZsetOperations
文字列
ValueOperations
BoundValueOpetations
しゅうごう
SetOperations
BoundSetOperations
リスト#リスト#
ListOperations
BoundListOperations
ハッシュ#ハッシュ#
HashOperations
BoundHashOperations
きすう
HyperLogLogOperations
BoundHyperLogLogOperaions
地理的位置
GeoOperations
BoundGeoOperations
コードの使用
@Autowired
private RedisTemplate redisTemplate;
@Test
void stringRedisTest() {
final ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations
.set("key1", "value1", Duration.ofMinutes(1));
final Object value = valueOperations.get("key1");
Assert.isTrue(Objects.equals("value1", value), "set ");
final HashOperations hashOperations = redisTemplate.opsForHash();
hashOperations.put("hash1", "f1", "v1");
hashOperations.put("hash1", "f2", "v2");
hashOperations.values("hash1").forEach(System.out::println);
}
同じ接続で複数回実行
コードの使用
@Test
void redisCallbackTest() {
redisTemplate.execute((RedisCallback) connection -> {
connection.set("rkey1".getBytes(), "rv1".getBytes());
connection.set("rkey2".getBytes(), "rv2".getBytes());
return null;
});
}
@Test
void sessionCallbackTest() {
redisTemplate.execute(new SessionCallback() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
final ListOperations listOperations = operations.opsForList();
listOperations.leftPush("sk1", "sv1");
listOperations.leftPush("sk1", "sv2");
listOperations.getOperations().expire("sk1", 1, TimeUnit.MINUTES);
listOperations.range("sk1", 0, 2).forEach(System.out::println);
return 1;
}
});
}
文字列アクション
最もよく使われるデータ型は実際にはあまり使われていませんが、現実のシーンでは、1つのオブジェクトやオブジェクトのリストを文字列に変換して記憶し、取り出すときにオブジェクトに変換するのが一般的です.
コード:
@Test
void stringTest() {
redisTemplate.opsForValue().set("stringKey1", "value1", 5, TimeUnit.MINUTES);
// , ;
redisTemplate.opsForValue().set("stringKey2", "1", 5, TimeUnit.MINUTES);
// , ,
redisTemplate.opsForValue().set("stringKey3", 1, 5, TimeUnit.MINUTES);
redisTemplate.opsForValue().increment("stringKey3",1);
redisTemplate.opsForValue().decrement("stringKey3",1);
//
final Long keySize = redisTemplate.opsForValue().size("stringKey1");
System.out.println(keySize);
//
Map map = new HashMap<>(4);
map.put("sk1",1L);
map.put("sk2",2L);
map.put("sk3",3L);
map.put("sk4",4L);
redisTemplate.opsForValue().multiSet(map);
redisTemplate.opsForValue().multiSetIfAbsent(map);
//
redisTemplate.opsForValue().multiGet(map.keySet()).forEach(System.out::println);
//getAndSet
final Object sk5Value = redisTemplate.opsForValue().getAndSet("sk5", 100);
System.out.println("sk5Value:"+sk5Value);
redisTemplate.opsForValue().append("sk5","hello redis");
System.out.println("sk5Value2:"+redisTemplate.opsForValue().get("sk5"));
// , ;
redisTemplate.opsForValue().setIfAbsent("sk6",1000,5,TimeUnit.MINUTES);
redisTemplate.opsForValue().setIfPresent("sk6",100,5,TimeUnit.MINUTES);
}
その他の方法:
より多くの方法をビジネスシーンで使用する必要があります
リストアクション
@Test
void listTest() {
stringRedisTemplate.opsForList().leftPush("lk1","lkv1");
stringRedisTemplate.opsForList().leftPushAll("lk2","lk2v1","lk2v2");
stringRedisTemplate.opsForList().leftPushAll("lk2",Arrays.asList("lk2v3","lk2v4"));
stringRedisTemplate.opsForList().leftPushIfPresent("lk3","lk3v1");
final List lk2ValuesList = stringRedisTemplate.opsForList().range("lk2", 0, 3);
System.out.println(lk2ValuesList);
}
コレクションアクション
@Test
void setTest() {
stringRedisTemplate.opsForSet().add("sk1","sk1v1","sk1v2","sk1v3");
stringRedisTemplate.opsForSet().add("sk2","sk1v1","sk2v2","sk2v3");
final Set sk1 = stringRedisTemplate.opsForSet().members("sk1");
final Set sk2 = stringRedisTemplate.opsForSet().members("sk2");
System.out.println("sk1: "+sk1);
System.out.println("sk2: "+sk2);
final Set intersect = stringRedisTemplate.opsForSet().intersect("sk1", "sk2");
System.out.println(" :" + intersect);
final Set union = stringRedisTemplate.opsForSet().union("sk1", "sk2");
System.out.println(" :" + union);
final Set difference = stringRedisTemplate.opsForSet().difference("sk1", "sk2");
System.out.println(" :"+ difference);
final Long size = stringRedisTemplate.opsForSet().size("sk1");
System.out.println("size for sk1 : " + size);
stringRedisTemplate.delete("sk1");
stringRedisTemplate.delete("sk2");
}
秩序化された集合アクション
@Test
void zsetTest() {
IntStream.rangeClosed(1,100).forEach(i->{
stringRedisTemplate.opsForZSet().add("zsk1",String.valueOf(i),i*10);
});
final Set> typedTupleSet = IntStream.rangeClosed(1, 100).mapToObj(i -> new DefaultTypedTuple(String.valueOf(i), (double) i * 11)).collect(Collectors.toSet());
stringRedisTemplate.opsForZSet().add("zsk2",typedTupleSet);
final Set zsk1 = stringRedisTemplate.opsForZSet().rangeByLex("zsk1", RedisZSetCommands.Range.range().gte(20).lte(100));
System.out.println(" :" + zsk1);
}
ハッシュ・アクション
@Test
void hashTest() {
stringRedisTemplate.opsForHash().put("hashk1","k1","v1");
stringRedisTemplate.opsForHash().put("hashk1","k2","v1");
stringRedisTemplate.opsForHash().put("hashk1","k3","v1");
stringRedisTemplate.opsForHash().putIfAbsent("hashk1","k4","new V1");
final List
Springbootにおけるredisの構成
構成は2つの部分に分けられ、接続プールと接続情報;次の表に、必要な構成を示します.
spring.redis.port=6379
spring.redis.host=localhost
spring.redis.password=
spring.redis.timeout=1000
#
spring.redis.lettuce.pool.min-idle=2
#
spring.redis.lettuce.pool.max-idle=4
#
spring.redis.lettuce.pool.max-active=8
#
spring.redis.lettuce.pool.max-wait=2000
#
spring.redis.lettuce.pool.time-between-eviction-runs=100
注記操作redis
CacheManager springを設定します.redis.cache.type=redis spring.redis.cache.name=redisCache
注記@EnableCachingで有効CachePut更新キャッシュ@CacheEvenicatクリアキャッシュ@CacheAbleクエリーキャッシュを使用
キャッシュは1つのクラスで相互に呼び出されて失効します:AOPに基づく動的エージェントは、エージェントクラスを生成していません;
package com.springbootpractice.demo.redis.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
/**
* :
* @author carter
* : 2020 01 21 7:00
**/
@Configuration
public class RedisConfig {
@Autowired private RedisTemplate redisTemplate;
@Bean
public RedisCacheManager redisCacheManager(){
RedisCacheWriter redisWrite = RedisCacheWriter.lockingRedisCacheWriter(redisTemplate.getConnectionFactory());
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration.prefixKeysWith("_demo_redis_");
configuration.entryTtl(Duration.ofMinutes(10));
configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new JdkSerializationRedisSerializer()));
RedisCacheManager redisCacheManager = new RedisCacheManager(redisWrite,configuration);
return redisCacheManager;
}
}
使用法
package com.springbootpractice.demo.redis.biz;
import com.springbootpractice.demo.redis.dao.entity.UserLoginExtEntity;
import com.springbootpractice.demo.redis.dao.mapper.UserLoginExtEntityMapper;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
* : user
* @author carter
* : 2020 01 21 6:40
**/
@Service
public class UserLoginExtBiz {
private final UserLoginExtEntityMapper userLoginExtEntityMapper;
public UserLoginExtBiz(UserLoginExtEntityMapper userLoginExtEntityMapper) {
this.userLoginExtEntityMapper = userLoginExtEntityMapper;
}
@Cacheable(value = "redisCache",key = "'getById:'+#id")
public UserLoginExtEntity getById(Integer id){
return userLoginExtEntityMapper.selectByPrimaryKey(id);
}
@CachePut(value = "redisCache",key = "'getById:'+#param.id")
public UserLoginExtEntity updateUserLoginExt(UserLoginExtEntity param){
userLoginExtEntityMapper.updateByPrimaryKeySelective(param);
return param;
}
@CacheEvict(value = "redisCache",key = "'getById:'+#id")
public int deleteUserLoginExt(Integer id){
return userLoginExtEntityMapper.logicalDeleteByPrimaryKey(id);
}
}
redisの特殊な使い方
redisでのトランザクションの使用方法
SessionCallbackのRedisOperationsのwatch-multi-execループ操作を利用している.watch:いくつかのkeyを監視する;Multi:トランザクションを開始します.exec:実行トランザクションwatchのkeyに対応する値が変化した場合(元の値に設定しても変化した場合)、トランザクションはロールバックされます.そうでなければ、正常にトランザクションを実行します.redisはトランザクションを実行するとき、すべて実行するか、すべて失敗し、他のredisクライアントに中断されず、redisトランザクションの下でデータの一貫性を保証します.
@Test
void transactionTest() {
final String ttk1 = "ttk1";
stringRedisTemplate.opsForValue().set(ttk1,"ttk1v1");
final List list = stringRedisTemplate.execute(new SessionCallback() {
@Override
public List execute(RedisOperations operations) throws DataAccessException {
System.out.println(" "+ttk1);
// ttk1 , set , ,
operations.watch(ttk1);
//
System.out.println(" ");
operations.multi();
operations.opsForList().leftPushAll("xxx_lk1", "v1", "v2", "v3");
final List xxx_lk1 = operations.opsForList().range("xxx_lk1", 0, 2);
System.out.println(xxx_lk1);
operations.opsForSet().add("xxx_sk1", "v1", "v2", "v3");
final Set xxx_sk1 = operations.opsForSet().members("xxx_sk1");
System.out.println(xxx_sk1);
//
final List list = operations.exec();
System.out.println(" ");
return list;
}
});
System.out.println(" :"+list);
}
一括実行redis操作
redisTemplate.executePipelined();
@Test
void pipelineTest() {
StopWatch stopWatch = new StopWatch("pipelineTest");
stopWatch.start();
final List
メッセージキュー
RedisMessageListenerContainerを定義し、topicとListenerを構成する必要があります.消費者としてredisTemplate.convertAndSendメソッドはメッセージを送信します.
Listenerの定義
package com.springbootpractice.demo.redis.listener;
import org.springframework.data.redis.connection.Message;
import org.springframework.stereotype.Component;
/**
* :redis
* @author carter
* : 2020 01 21 5:51
**/
@Component
public class MyRedisMessageListener implements org.springframework.data.redis.connection.MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
System.out.println("MyRedisMessageListener topic:"+new String(pattern) +" :"+ new String(message.getBody()));
}
}
Listenerコンテナの登録
package com.springbootpractice.demo.redis.listener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* : ,
* @author carter
* : 2020 01 21 5:55
**/
@Configuration
public class RedisListenerConfig {
public static final String MY_CHANNEL = "myChannel";
private final MyRedisMessageListener myRedisMessageListener;
private final MyRedisMessageListener2 myRedisMessageListener2;
private final RedisTemplate redisTemplate;
public RedisListenerConfig(MyRedisMessageListener myRedisMessageListener, MyRedisMessageListener2 myRedisMessageListener2, RedisTemplate redisTemplate) {
this.myRedisMessageListener = myRedisMessageListener;
this.myRedisMessageListener2 = myRedisMessageListener2;
this.redisTemplate = redisTemplate;
}
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer() {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(redisTemplate.getConnectionFactory());
final ExecutorService taskExecutor = new ThreadPoolExecutor(1,
2, 30, TimeUnit.SECONDS, new LinkedBlockingDeque<>(2000));
redisMessageListenerContainer.setTaskExecutor(taskExecutor);
final Topic myChannel = new ChannelTopic(MY_CHANNEL);
redisMessageListenerContainer.addMessageListener(myRedisMessageListener, myChannel);
redisMessageListenerContainer.addMessageListener(myRedisMessageListener2, myChannel);
System.out.println(" redis !");
return redisMessageListenerContainer;
}
}
テストコード
publish myChannel helloworld
package com.springbootpractice.demo.redis.web;
import com.springbootpractice.demo.redis.listener.RedisListenerConfig;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
/**
* :TODO
* @author carter
* : 2020 01 21 6:22
**/
@RestController
public class TestController {
private final StringRedisTemplate stringRedisTemplate;
public TestController(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
@GetMapping(path = "/send/{message}")
public void publishMessage(@PathVariable("message") String message){
stringRedisTemplate.convertAndSend(RedisListenerConfig.MY_CHANNEL,message);
}
}
luaスクリプトの使用
使用するredisTemplate.execute(RedisScript,List,List);
@GetMapping(path = "/lua/{k1}/{v1}/{k2}/{v2}")
public Long publishMessage(@PathVariable("k1") String k1,@PathVariable("k2") String k2,@PathVariable("v1") String v1,@PathVariable("v2") String v2){
DefaultRedisScript redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(LuaScript.lua1);
redisScript.setResultType(Long.class);
return stringRedisTemplate.execute(redisScript, Arrays.asList(k1, k2), v1, v2);
}
小結
この記事では、次のことを学ぶことができます.
コードポイントを取得します!
美人はやはり見せなければならない.
オリジナルは容易ではありません.転載は出典を明記してください.