1. 循環請求
最容易想到也是最耗時的操作,不推薦使用。簡單樣例如下
@Service
public class RedisService {
@Resource
private RedisTemplate<String,Object> template;
public void multiSave(Map<String,String> source) {
for(Map.Entry<String,String> item : source.entrySet()) {
template.opsForValue().set(item.getKey(), item.getValue());
}
}
}
2. pipe請求
流水線操作,其實就是一次性請求把所有命令發過去,不再等待他的返回,節省的是http請求時間。
需要注意的是必須要自己序列化,我此處使用RedisSerializer.string()始終是一個對象,但是如果json序列對象RedisSerializer.json()每次都是新對象,這個就建議自己聲明一個變量保存
下面的樣例為求優雅,用的是jdk8的一些語法和對象,如果讀者的jdk<8, 可以找找其他網上不那么優雅的版本
@Service
public class RedisService {
@Resource
private RedisTemplate<String, Object> template;
public void multiSave(Map<String, String> source) {
template.executePipelined((RedisCallback<Object>) connection -> {
// 這里邏輯簡單不會拋異常
// 否則需要加上try...catch...finally防止鏈接未正常關閉 造成泄漏
connection.openPipeline();
source.forEach((key, value) -> {
// hset zset都是可以用的,但是要序列化
connection.set(RedisSerializer.string().serialize(key),
RedisSerializer.string().serialize(value));
// 設置過期時間 10天
connection.expire(RedisSerializer.string().serialize(key), TimeUnit.DAYS.toSeconds(10));
});
connection.close();
// executePipelined源碼要求RedisCallback必須返回null,否則拋異常
return null;
});
}
}
- multiSet
原生支持的批量操作,速度最快。
但是不靈活,使用范圍較有限。比如hset支持一次多個插入,但是opsForHash()就沒有multiSet,只有multiGet
也沒有一起設置過期時間,仔細衡量業務場景后使用
@Service
public class RedisService {
@Resource
private RedisTemplate<String,Object> template;
public void multiSave(Map<String,String> source) {
template.opsForValue().multiSet(source);
}
}
4. 總結對比
這里就用別人的測試結果吧,公司內網開發,上面代碼都是手打;若有錯漏請不吝指教
10萬次插入的情況下
普通set消耗9010毫秒
管道set消耗1606毫秒
批量set消耗18毫秒
性能測試來源:https://blog.csdn.net/weixin_41677422/article/details/108626587