Back/DB

[MySQL, Redis, Node.js] Cache를 활용한 Update query 속도 개선

그지같은 Update 속도 때문에, 여러 곳에서 병목 현상이 났다.

프로덕트 성격상, update, Insert, delete가 활발한 table이 있는데, 이 곳에서 데드락도 잘 걸리고,

고통스러웠다.

매번 투매니커넥션 뜰 때마다, 프로세스 리스트에서 병목 현상을 일으키는 쿼리를 보고, 놀러갈 때도, 노트북을 들고다니며, 눈물의 스크립트를 날리는 고통을 받았다...

이번에 시간이 좀 나서, 어떻게든 개선해보려했다.

전체를 다 고치는건, 공수가 너무 들어서 힘들었고, 일단 임시조치를 취했다. 처음엔 서브쿼리, 임시테이블을 활용했으나, 이것도 여의치 않아서, 그냥 캐시를 활용하기로 했다.


Redis를 활용해서, Pk를 캐시로 만들었다.

redis.commend는 미리 모듈화해 둔 redis 명령어 함수다.

  const menuIdxCacheResultForUpdateQuerySpeed = await redis.commend.get(
    `${memberIdx}createdAt${created_at}time${time}`,
  );

  if (menuIdxCacheResultForUpdateQuerySpeed === null) {
    await redis.commend.set(
      `${memberIdx}createdAt${createdAt}time${time}`,
      [menuIdx].toString(),
      600,
    );
  } else {
    let menuRegIdxCacheArray = menuRegIdxCacheResultForUpdateQuerySpeed.split(',');
    menuIdxCacheArray.push(menuIdx);

    await redis.commend.set(
      `${member.memberIdx}createdAt${createdAt}time${time}`,
      menuIdxCacheArray.toString(),
      600,
    );
  }

배열을 만들어서, 스트링으로 바꾼 후 저장하고,

기존에 값이 있으면, 다시 배열로 바꿔서,push 해준 후 스트링 변환하고, 저장한다.

그 후 PK와 관련된 업데이트 구문이 있다면 기존 캐시를 활용해서, PK값을 이용해 update or delete 해준다.

    const menuIdxCache = await redis.commend.get(
      `${member.memberIdx}createdAt${createdAt}time${time}`,
    );

    if (menuIdxCache !== null) {
      menuIdxCache = menuIdxCache.split(',');

      await mysqlWrite.query(
        `
        UPDATE table
        SET
        change = 1,
        updated_at = DATE_FORMAT(NOW(), '%Y-%m-%d')
        WHERE menu_idx IN (?)
        `,
        [menuIdxCache],
      );
      
	await redis.commend.del(`${member.memberIdx}createdAt${createdAt}time${time}`)
    }


실제로 쿼리를 날릴 땐, 쿼리를 모듈화 해서 사용했다.

현재 프로덕트에서 ORM을 안쓰고, 직접 쿼리를 날려서 쓰는데,

update, delete, insert, select가 매우 활발한 table에선 이상하게 자꾸 데드락이 걸렸다.

임시테이블을 만들어서 조치를 취해봐도, 문제가 간혹 생겼다.

기왕 캐시서버 만들기도 한거.. 잘 활용하고 있었기도 하고,

이런 부분에도 조금씩 적용해서 쓰기 시작하니까,

DB부하도 많이 줄고, 오류도 상당 부분 사라졌다.

그냥 처음부터 ORM 썼으면 이런거 알아서 다 잡아줬을텐데, 괜히 처음에 멋모르고 쿼리문 좀 공부하겠다고 깝친다고..

현재 프로덕트 이해도가 가장 높은 사람은 난데,

여러 레퍼런스를 참고해도, 어떻게 저떻게 라우터나 쿼리를 손보고 개선해서 해결할 수 있다고, 판단되지 않았고,

그럴만한 시간도, 레벨도 내가 갖추지 못했다.

그래서 이게 정답은 아니겠지만.. 꼼수처럼 쓴 방법이긴한데..

일단 오늘은 이걸로 임시 해결...

'Back > DB' 카테고리의 다른 글

MySQL, PostgreSQL  (0) 2023.03.03
[Node.js, MySQL] Pool.getConnection() 속도 문제  (0) 2022.02.21