大量数据导入的方式
单个命令的执行流程
一次命令的响应时间 = 1次往返的网络传输耗时 + 1次Redis执行命令耗时
N条命令依次执行
N次命令的响应时间 = N次往返的网络传输耗时 + N次Redis执行命令耗时
N条命令批量执行
N次命令的响应时间 = 1次往返的网络传输耗时 + N次Redis执行命令耗时
Redis提供了很多Mxxx这样的命令,可以实现批量插入数据,例如:
mset
hmset
利用mset批量插入10万条数据:
127.0.0.1:6379> help MSET
MSET key value [key value ...]
summary: Set multiple keys to multiple values
since: 1.0.1
group: string
127.0.0.1:6379>
@Test
void testMxx() {
String[] arr = new String[2000];
int j;
for (int i = 1; i <= 100000; i++) {
j = (i % 1000) << 1;
arr[j] = "test:key_" + i;
arr[j + 1] = "value_" + i;
if (j == 0) {
jedis.mset(arr);
}
}
}
注意:不要在一次批处理中传输太多命令,否则单次命令占用带宽过多,会导致网络阻塞。
Pipeline
MSET虽然可以批处理,但是却只能操作部分数据类型,因此如果有对复杂数据类型的批处理需要,建议使用Pipeline功能:
@Test
void testPipeline() {
// 创建管道
Pipeline pipeline = jedis.pipelined();
for (int i = 1; i <= 100000; i++) {
// 放入命令到管道
pipeline.set("test:key_" + i, "value_" + i);
if (i % 1000 == 0) {
// 每放入1000条命令,批量执行
pipeline.sync();
}
}
}
批量处理的方案:
-- 原生的M操作
-- Pipeline批处理
注意事项:
-- 批处理时不建议一次携带太多命令
-- Pipeline的多个命令之间不具备原子性
集群下的批处理
如MSET或Pipeline这样的批处理需要在一次请求中携带多条命令,而此时如果Redis是一个集群,那批处理命令的多个key必须落在一个插槽中,否则就会导致执行失败。