一、背景
二、操作
List<String> keys = new ArrayList<>();
for (Book e : booklist) {
String key = generateKey.getKey(e);
keys.add(key);
}
List<Serializable> resultStr = template.opsForValue().multiGet(
2.RedisTemplate的Pipeline使用
为什么Pipelining这么快?
先看看原来的多条命令,是如何执行的:
Redis Client->>Redis Server: 发送第1个命令
Redis Server->>Redis Client: 响应第1个命令
Redis Client->>Redis Server: 发送第2个命令
Redis Server->>Redis Client: 响应第2个命令
Redis Client->>Redis Server: 发送第n个命令
Redis Server->>Redis Client: 响应第n个命令
Pipeling机制是怎样的呢: Redis Client->>Redis Server: 发送第1个命令(缓存在Redis Client,未即时发送) Redis Client->>Redis Server: 发送第2个命令(缓存在Redis Client,未即时发送) Redis Client->>Redis Server: 发送第n个命令(缓存在Redis Client,未即时发送) Redis Client->>Redis Server: 发送累积的命令 Redis Server->>Redis Client: 响应第1、2、n个命令
package cn.chinotan.controller;
import cn.chinotan.service.RedisService;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @program: test
* @description: redis批量数据测试
* @author: xingcheng
* @create: 2019-03-16 16:26
**/
@RestController
@RequestMapping("/redisBatch")
@Log
public class RedisBatchController {
@Autowired
StringRedisTemplate redisTemplate;
@Autowired
Map<String, RedisService> redisServiceMap;
/**
* VALUE缓存时间 3分钟
*/
public static final Integer VALUE_TIME = 1;
/**
* 测试列表长度
*/
public static final Integer SIZE = 100000;
@GetMapping(value = "/test/{model}")
public Object hello(@PathVariable("model") String model) {
List<Map<String, String>> saveList = new ArrayList<>(SIZE);
List<String> keyList = new ArrayList<>(SIZE);
for (int i = 0; i < SIZE; i++) {
Map<String, String> objectObjectMap = new HashMap<>();
String key = String.valueOf(i);
objectObjectMap.put("key", key);
StringBuilder sb = new StringBuilder();
objectObjectMap.put("value", sb.append("value").append(i).toString());
saveList.add(objectObjectMap);
// 记录全部key
keyList.add(key);
}
// 获取对应的实现
RedisService redisService = redisServiceMap.get(model);
long saveStart = System.currentTimeMillis();
redisService.batchInsert(saveList, TimeUnit.MINUTES, VALUE_TIME);
long saveEnd = System.currentTimeMillis();
log.info("插入耗时:" + (saveEnd - saveStart) + " ms");
// 批量获取
long getStart = System.currentTimeMillis();
List<String> valueList = redisService.batchGet(keyList);
long getEnd = System.currentTimeMillis();
log.info("获取耗时:" + (getEnd - getStart) + " ms");
return valueList;
}
}
package cn.chinotan.controller;
import cn.chinotan.service.RedisService;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @program: test
* @description: redis批量数据测试
* @author: xingcheng
* @create: 2019-03-16 16:26
**/
@RestController
@RequestMapping("/redisBatch")
@Log
public class RedisBatchController {
@Autowired
StringRedisTemplate redisTemplate;
@Autowired
Map<String, RedisService> redisServiceMap;
/**
* VALUE缓存时间 3分钟
*/
public static final Integer VALUE_TIME = 1;
/**
* 测试列表长度
*/
public static final Integer SIZE = 100000;
@GetMapping(value = "/test/{model}")
public Object hello(@PathVariable("model") String model) {
List<Map<String, String>> saveList = new ArrayList<>(SIZE);
List<String> keyList = new ArrayList<>(SIZE);
for (int i = 0; i < SIZE; i++) {
Map<String, String> objectObjectMap = new HashMap<>();
String key = String.valueOf(i);
objectObjectMap.put("key", key);
StringBuilder sb = new StringBuilder();
objectObjectMap.put("value", sb.append("value").append(i).toString());
saveList.add(objectObjectMap);
// 记录全部key
keyList.add(key);
}
// 获取对应的实现
RedisService redisService = redisServiceMap.get(model);
long saveStart = System.currentTimeMillis();
redisService.batchInsert(saveList, TimeUnit.MINUTES, VALUE_TIME);
long saveEnd = System.currentTimeMillis();
log.info("插入耗时:" + (saveEnd - saveStart) + " ms");
// 批量获取
long getStart = System.currentTimeMillis();
List<String> valueList = redisService.batchGet(keyList);
long getEnd = System.currentTimeMillis();
log.info("获取耗时:" + (getEnd - getStart) + " ms");
return valueList;
}
}
package cn.chinotan.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @program: test
* @description: redis管道操作
* @author: xingcheng
* @create: 2019-03-16 16:47
**/
@Service("pipe")
public class RedisPipelineService implements RedisService {
@Autowired
StringRedisTemplate redisTemplate;
@Override
public void batchInsert(List<Map<String, String>> saveList, TimeUnit unit, int timeout) {
/* 插入多条数据 */
redisTemplate.executePipelined(new SessionCallback<Object>() {
@Override
public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
for (Map<String, String> needSave : saveList) {
redisTemplate.opsForValue().set(needSave.get("key"), needSave.get("value"), timeout,unit);
}
return null;
}
});
}
@Override
public List<String> batchGet(List<String> keyList) {
/* 批量获取多条数据 */
List<Object> objects = redisTemplate.executePipelined(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection redisConnection) throws DataAccessException {
StringRedisConnection stringRedisConnection = (StringRedisConnection) redisConnection;
for (String key : keyList) {
stringRedisConnection.get(key);
}
return null;
}
});
List<String> collect = objects.stream().map(val -> String.valueOf(val)).collect(Collectors.toList());
return collect;
}
}
package cn.chinotan.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @program: test
* @description: redis普通遍历操作
* @author: xingcheng
* @create: 2019-03-16 16:47
**/
@Service("generic")
public class RedisGenericService implements RedisService {
@Autowired
StringRedisTemplate redisTemplate;
@Override
public void batchInsert(List<Map<String, String>> saveList, TimeUnit unit, int timeout) {
for (Map<String, String> needSave : saveList) {
redisTemplate.opsForValue().set(needSave.get("key"), needSave.get("value"), timeout,unit);
}
}
@Override
public List<String> batchGet(List<String> keyList) {
List<String> values = new ArrayList<>(keyList.size());
for (String key : keyList) {
String value = redisTemplate.opsForValue().get(key);
values.add(value);
}
return values;
}
}
测试结果:
可以看到性能提升了20倍之多
基于其特性,它有两个明显的局限性:
(adsbygoogle = window.adsbygoogle || []).push({});