SpringBoot 整合 Redis

1. pom.xml 文件中添加 Redis 依賴java

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
	<exclusions>
		<exclusion>
			<groupId>io.lettuce</groupId>
			<artifactId>lettuce-core</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
</dependency>

2. application.properties 文件中添加 Redis 相關配置redis

spring.redis.host=10.112.77.2
spring.redis.port=6379
spring.redis.database=0
spring.redis.password=
spring.redis.timeout=1s

spring.redis.jedis.pool.min-idle=5
spring.redis.jedis.pool.max-active=10
spring.redis.jedis.pool.max-idle=10
spring.redis.jedis.pool.max-wait=2s

3. 在代碼相關位置使用 @Resource 注入 RedisTemplate 或者 @Autowired 注入 StringRedisTemplatespring

@Controller
@RequestMapping("/user")
public class UserController {
	@Resource
	private RedisTemplate<String, String> redisTemplate;
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	
	@RequestMapping("/testRedis")
	@ResponseBody
	public Integer testRedis() {
		stringRedisTemplate.opsForValue().set("str1", "str11");
		stringRedisTemplate.opsForList().leftPush("list1", "list11");
		stringRedisTemplate.opsForHash().put("map1", "key1", "value1");
		stringRedisTemplate.opsForSet().add("set1", "set11", "set22");
		stringRedisTemplate.opsForZSet().add("zset1", "zset11", 1.0);
		Set<String> set = stringRedisTemplate.opsForSet().members("set1");
		Object value = stringRedisTemplate.opsForHash().get("map1", "key1");
		return 1;
	}
}
@RequestMapping("/testRedis2")
@ResponseBody
public Integer testRedis2() {
    // 使用boundSetOps進行對應key的頻繁操做
	BoundSetOperations<String, String> boundSetOperations = stringRedisTemplate.boundSetOps("set1");
	boundSetOperations.add("set33", "set44", "set55");
	return 1;
}

4. 在 SpringBoot 主類中設置 redis 序列化方式數據庫

@PostConstruct 註解修飾非靜態的 void 方法, 在 servlet 的構造方法以後 init() 方法以前執行bash

@PreDestory 註解修飾的非靜態的 void 方法, 會在 servlet 的 destory() 方法以前執行 app

@PostConstruct
public void initRedisTemplate() {
	RedisSerializer<String> stringSerializer = redisTemplate.getStringSerializer();
	redisTemplate.setKeySerializer(stringSerializer);
	redisTemplate.setStringSerializer(stringSerializer);
	redisTemplate.setHashKeySerializer(stringSerializer);
}

5. 使用 SessionCallback 和 RedisCallback 接口ide

經過使用這兩個接口讓 RedisTemplate 回調, 能夠在同一條鏈接下執行多條 Redis 命令, 避免 RedisTemplate 屢次獲取不一樣的鏈接spring-boot

SessionCallback 是封裝良好, 對開發者友好, 實際的開發中儘可能選擇使用它性能

RedisCallback 接口比較底層, 須要處理的比較多, 可讀性差, 實際開發中儘可能不使用它.net

6. Redis 的事務

watch......multi......exec 是 Redis 的事務流程

watch 監控 redis 的一些鍵值是否發生變化, multi 開始事務, 開啓事務後, 不會立刻執行命令, 而是存放在一個隊列裏, exec 命令是執行事務, 若是 watch 監控的鍵值發生變化(哪怕新值和原值同樣, 也是發生變化), 就取消事務的執行, 若是鍵值沒有發生變化, 就執行事務. 執行事務的時候, 若是執行某條命令報錯, 也只能是報錯, 後面的命令會正常執行, 這是和數據庫事務不同的地方, 因此 redis 的事務時, 要不都執行, 要不都不執行, 數據庫事務是要不都成功, 要不都失敗.

// 貌似 executePipelined() 流水線方法是不能用來執行事務的.
stringRedisTemplate.execute(new SessionCallback<Object>() {
	@SuppressWarnings({"unchecked", "rawtypes" })
	@Override
	public Object execute(RedisOperations operations) throws DataAccessException {
		operations.watch("str1");
		operations.multi();
		operations.opsForValue().set("str2", "str2");
		operations.opsForValue().set("str3", "str3");
		operations.exec();
		return null;
	}
});

7. Redis 的流水線

executePipelined() 方法用來批量執行語句, 性能高

@RequestMapping("/testRedis5")
@ResponseBody
public Integer testRedis5() {
	long start = System.currentTimeMillis();
	stringRedisTemplate.executePipelined(new SessionCallback<Object>() {
		@SuppressWarnings({ "rawtypes", "unchecked" })
		@Override
		public Object execute(RedisOperations operations) throws DataAccessException {
			for (int i = 0; i < 100000; i++) {
				operations.opsForValue().set("str_" + i, "value_"+i);
				String value = (String) operations.opsForValue().get("strr" + i);
				if (i == 900) {
					System.out.println("值爲 " + value);
				}
			}
			return null;
		}
	});
	System.out.println("time: " + (System.currentTimeMillis() - start));
	return 1;
}
相關文章
相關標籤/搜索