RedisTemplate批量添加利用教程,利用pipeline批量利用;multiSet()批量利用;for循环批量利用
一、利用pipeline的长处
相识redis的小同伴都知道,redis是一个高性能的单线程的key-value数据库。它的实验过程为:
(1)发送死令-〉(2)下令排队-〉(3)下令实验-〉(4)返回结果
如果我们利用redis举行批量插入数据,正常环境下相当于将以上四个步调批量实验N次。(1)和(4)称为Round Trip Time(RTT,往返时间)。在一条简单指令中,每每(1)(4)步调之和大过于(2)(3)步调之和,怎样举行优化?Redis提供了pipeline管道机制,它能将一组Redis下令举行组装,通过一次RTT传输给Redis,并将这组Redis下令的实验结果按序次返回给客户端。
优缺点总结:
- 1、性能对比:multiSet()>pipeline管道>平凡for循环set
- 2、扩展性强,可以支持设置失效时间。multiSet()不支持失效时间的设置
二、批量利用的工具类
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.RedisStringCommands;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.types.Expiration;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.stereotype.Component;import java.util.List;import java.util.Map;/** * @author: huangyibo * @Date: 2022/6/23 16:15 * @Description: */@Componentpublic class BatchRunRedisUtil { @Autowired private RedisTemplate<String, Object> stringRedisTemplate; /** * 批量添加 * @param map */ public void batchSet(Map<String, String> map) { stringRedisTemplate.opsForValue().multiSet(map); } /** * 批量添加 而且设置失效时间 * @param map * @param seconds */ public void batchSetOrExpire(Map<String, String> map, Long seconds) { RedisSerializer<String> serializer = stringRedisTemplate.getStringSerializer(); stringRedisTemplate.executePipelined(new RedisCallback<String>() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { map.forEach((key, value) -> { connection.set(serializer.serialize(key), serializer.serialize(value), Expiration.seconds(seconds), RedisStringCommands.SetOption.UPSERT); }); return null; } }, serializer); } /** * 批量获取 * @param list * @return */ public List<Object> batchGet(List<String> list) { List<Object> objectList = stringRedisTemplate.opsForValue().multiGet(list); return objectList; } /** * Redis批量Delete * @param list */ public void batchDelete(List<String> list) { stringRedisTemplate.delete(list); }}三、性能测试
通过for循环来向redis插入数据,通过pipeline插入数据,通过利用redisTemplate.opsForValue().multiSet(map)插入数据检察实验时间。
import com.demo.util.BatchRunRedisUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.data.redis.core.RedisTemplate;import java.util.HashMap;import java.util.Map;@SpringBootApplicationpublic class DemoApplication implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Autowired private RedisTemplate<String, Object> stringRedisTemplate; @Autowired private BatchRunRedisUtil batchRunRedisUtil; @Override public void run(String... args) throws Exception { //for循环批量添加 long startTime = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { stringRedisTemplate.opsForValue().set("aaa" + i, "a", 60); } long endTime = System.currentTimeMillis(); System.out.println("平凡set斲丧" + (endTime - startTime) + "毫秒"); //利用pipeline批量利用 long startTime2 = System.currentTimeMillis(); Map map = new HashMap(100000); for (int i = 0; i < 100000; i++) { map.put("bbb" + i, "b"); } batchRunRedisUtil.batchSetOrExpire(map, 60l); long endTime2 = System.currentTimeMillis(); System.out.println("管道set斲丧" + (endTime2 - startTime2) + "毫秒"); //multiSet()批量利用 long startTime3 = System.currentTimeMillis(); Map map2 = new HashMap(100000); for (int i = 0; i < 100000; i++) { map2.put("ccc" + i, "b"); } batchRunRedisUtil.batchSet(map2); long endTime3 = System.currentTimeMillis(); System.out.println("批量set斲丧" + (endTime3 - startTime3) + "毫秒"); }}在本机分别实验了三次结果:
平凡set斲丧9010毫秒管道set斲丧1606毫秒批量set斲丧18毫秒平凡set斲丧8228毫秒管道set斲丧1059毫秒批量set斲丧14毫秒平凡set斲丧8365毫秒管道set斲丧1092毫秒批量set斲丧13毫秒通过比较发现,逐条实验时间是pipeline实验均匀时间的8倍!这是在本机测试的结果,理论上,客户端与服务端的网络耽误越大,性能体能越显着。
当然,pipeline性能提升虽然显着,但是每次管道里下令个数太多的话,也会造成客户端相应时间变久,网络传输壅闭。最好还是根据业务环境,将大的pipeline拆分成多个小的pipeline来实验。
如果不消设置失效时间的话最好利用redisTemplate.opsForValue().multiSet(map)方法来添加
参考:
https://blog.csdn.net/weixin_41677422/article/details/108626587 |