@@ -25,29 +25,39 @@ public class ConcertSearchRedisTemplate {
2525
2626 public void addAllWordsWithWeight (List <WeightedString > weightedStrings ) {
2727 // PipeLine 사용해서 한번에 처리 -> IO 시간 감소
28- redisTemplate .executePipelined ((RedisCallback <?>) connection ->{
29- for (WeightedString weightedString : weightedStrings ) {
30- String id = String .valueOf (weightedString .getConcertId ());
31- String word = weightedString .getWord ();
32- double score = weightedString .getScore ();
28+ // 대량의 파이프라인 작업시 Zset 양이 너무 많으면 set 처리가 누락되는 문제 발생 -> 한번에 batch X, 여러번 나누어서 처리
29+ int batchSize = 50 ;
30+ for (int i = 0 ; i < weightedStrings .size (); i +=batchSize ) {
31+ List <WeightedString > batch = weightedStrings .subList (i , Math .min (i + batchSize , weightedStrings .size ()));
32+ redisTemplate .executePipelined ((RedisCallback <?>) connection ->{
33+ for (WeightedString weightedString : batch ) {
34+ String id = String .valueOf (weightedString .getConcertId ());
35+ String word = weightedString .getWord ();
36+ double score = weightedString .getScore ();
3337
34- // 검색 결과를 ID - 제목 쌍으로 저장
35- connection .commands ().set ((CONCERT_ID_KEY + id ).getBytes (StandardCharsets .UTF_8 ),word .getBytes (StandardCharsets .UTF_8 ));
38+ // 직렬화 도구 명시적 사용 (Template 설정과 일치)
39+ byte [] key = redisTemplate .getStringSerializer ().serialize (CONCERT_ID_KEY + id );
40+ byte [] value = redisTemplate .getStringSerializer ().serialize (word );
41+ byte [] idByte = redisTemplate .getStringSerializer ().serialize (id );
3642
37- // 역 인덱싱
38- for (int i = 0 ;i <word .length ();i ++){
39- for (int j = i +1 ;j <= word .length ();j ++ ){
40- String subWord = word .substring (i ,j );
41- // 공백은 검색어 인덱스에서 제외
42- if (subWord .isBlank ()) continue ;
43- // 서브 문자열을 인덱스 키, 값은 ID 값으로 해서 저장
44- byte [] indexKey = (INDEX_KEY + subWord ).getBytes (StandardCharsets .UTF_8 );
45- connection .zAdd (indexKey ,score ,id .getBytes (StandardCharsets .UTF_8 ));
43+ // 검색 결과를 ID - 제목 쌍으로 저장
44+ connection .commands ().set (key ,value );
45+
46+ // 역 인덱싱
47+ for (int k = 0 ;k <word .length ();k ++){
48+ for (int j = k +1 ;j <= word .length ();j ++ ){
49+ String subWord = word .substring (k ,j );
50+ // 공백은 검색어 인덱스에서 제외
51+ if (subWord .isBlank ()) continue ;
52+ // 서브 문자열을 인덱스 키, 값은 ID 값으로 해서 저장
53+ byte [] indexKey = redisTemplate .getStringSerializer ().serialize (INDEX_KEY + subWord );
54+ connection .zAdd (indexKey , score , idByte );
55+ }
4656 }
4757 }
48- }
49- return null ;
50- });
58+ return null ;
59+ }) ;
60+ }
5161 }
5262
5363 public List <AutoCompleteItem > getAutoCompleteWord (String keyword , int start , int end ) {
0 commit comments