redis cache with fcm alarm

Jaymee·2021년 10월 16일
0

yeomanda 프로젝트에서 채팅 대화들을 캐시에 저장을 하고 추후에 디비 저장 요청 api가 날라오면 그때 디비에 저장을 하도록 했었다.
그렇게 해야 과부하도 생기지 않고, 서버가 터지지 않을 것 이라고 생각했기 때문이다.
하지만 문제가 생겼다.
대화를 보낼때 마다 대상에게 알람을 보내기 위해 fcm을 통해서 알람을 보내려고 했는데, 생각해보니 그렇게 해서 알람이 가면 디비에 저장이 되지 않은 상태의 대화들을 볼 것 아닌가...
알람을 보냄과 동시에 디비에 저장을 하면 굳이 캐시를 써야 하는가 하는 의문도 생겼다.
결국 알람을 보내기 전에 채팅창들을 업데이트(디비 최신화)를 해야하는데, 그렇다면 디비에 저장을 하고 알람을 보내야 한다.
실무자들은 어떻게 구현했을까... 카카오톡은 어떻게 한거지..?


수정하기 전 코드는 아래와 같다.

socket.on('message', async function(data){
    /**
    * data - room_id, token, content
    */
    const nowDate = new Date();
    const token = socket.token = data.token
    const content = socket.content = data.content
    const room_id = socket.room_id = data.room_id
    const sender = parseJwt(token).email
    const name = parseJwt(token).name
    const sendTime = nowDate.toString()

    const res = {
      'message' : content,
      'senderEmail' : sender,
      'time' : sendTime,
      'senderName' : name
    }
    io.to(room_id).emit('message', res)
    /**
     * try to store in redis cache
     */
    try{
      // 문제점 - 스트링으로 append해서 저장하면 나중에 split 해야 하는데 그 기준은...?
      const newChat = {
        "createdAt" : sendTime,
        "senderEmail" : sender,
        "content" : content,
        "senderName" : name
      }
      client.sadd(room_id, JSON.stringify(newChat))
      
    }catch(err){
      console.log(err)
    }

이와 같이 client.sadd()를 통해서 캐시에 저장해놓고,

client.smembers(room_id, async(err, data) => {
            if(data.length){
                data.filter((d)=> {
                    const temp = JSON.parse(d)
                    newMessage.push(temp)
                    
                })
                const params_to_put_message = {
                    TableName : chatConfig.aws_table_name,
                    Item : {
                        "room_id" : room_id,
                        "members" : chatRoom.Items[0].members,
                        "teams" : chatRoom.Items[0].teams,
                        "chatMessages" : newMessage
                    } 
                };
                const resultChat = await docClient.put(params_to_put_message).promise()
                return res.status(statusCode.OK).send(util.success(statusCode.OK, responseMessage.UPDATE_MESSAGE))
            }else{
                return res.status(statusCode.OK).send(util.fail(statusCode.NO_CONTENT, responseMessage.NO_MESSAGES))
            }
        })
        client.del(room_id) // 특정 캐시만 지우고 싶은데...

아래와 같이 client.smembers() 를 통해 캐시에서 데이터를 가져와 디비에 저장을 한다. 추후에 client.del() 을 통해 특정 캐시를 지우게 된다.


하지만 변경후...
바로바로 디비에 저장을 하게 했다.
이러면 무조건 디비 과부하가 걸릴 것 같은데... 다른 방법을 생각해봐야겠다.

profile
backend developer

0개의 댓글