본문 바로가기

Redis

ioredis 해시

ioredis
ioredis를 선택한 이유 

 

nodejs환경에서 사용할 수 있는 redis라이브러리는 크게 2가지가 있다.

1. node-redis

2. ioredis

 

이전에는 node-redisioredis의 성능차이가 있었으나 node-redisv4로 넘어오며 거의 차이가 없다고 봐도 무방하다고 한다.

 

그럼에도 ioredis를 선택한 이유는 클러스터를 지원하기 때문이다.

 

ioredisredis 클러스터를 지원하여 여러개의 redis인스턴스에서 데이터를 분산 저장하고 관리 할 수 있기 때문에 

분산서버가 중요한 게임서버 개발자가 되기 위해 익혀두면 좋다고 판단하여 ioredis 사용에 익숙해질겸 ioredis를 선택하였다.

 

기본적인 사용법은 아래 문서를 참조했다.

ioredis 문서

 

ioredis/examples/zset.js at main · redis/ioredis

🚀 A robust, performance-focused, and full-featured Redis client for Node.js. - redis/ioredis

github.com


 

많은 시행착오를 겪은 결과 이번 프로젝트에서 주로 사용하게 된 ioredis hash자료형을 알아보자

 

redis hash

 

해시는 키 - 값 쌍의 집합으로 , 여러개의 필드를 가질 수 있는 데이터 구조이다.

해시는 주로 객체를 저장하는데 사용되며 각 필드는 이름과 값을 가진다. 예를 들어 사용자 정보를 해시로 저장할 수 있다.

  • 해시의 특징

해시는 작은 데이터의 조각을 저장할때 메모리 효율이 높으며 

관련된 데이터를 그룹화 하여 관리할 수 있다.

또한 특정 필드에 대해 빠르게 읽기 및 쓰기가 가능하다.


ioreids에서 해시를 사용하는 기본적인 방법
1. ioredis 라이브러리를 다운받는다.(npm,yarn 등 사용, 해당글에서는 yarn 사용)
yarn add ioreids​

2. ioredis 인스턴스 생성(host,port,password 지정 가능)
const redisClient = new Redis({
  host: 127.0.0.1 // Redis 클라우드 호스트
  port: 6379 // Redis 클라우드 포트
  password: 1234 // Redis 클라우드 비밀번호
});


3.해시에 데이터 저장

await redisClient.hset(key, ...Object.entries(val).flat()); //키값과 배열을 평탄화하여 저장

await redisClient.hset(key, field, val); // 키와 필드 벨류를 모두입력해 저장


4. 해시에서 데이터 읽기

await redisClient.hget(key, field)//키와 필드로 벨류값 찾기

await redisClient.hgetall(key)//해당 키의 모든 필드와 벨류를 가져옴


5.redis 함수로 사용

  // 데이터 저장 / 사용예시 : setRedis("홍길동","퇴근시간",3600)
  setRedis: async (key, val, ex) => {
    if (ex) {
      return await redisClient.set(key, val, 'EX', ex);
    } else {
      return await redisClient.set(key, val);
    }
  },
  
----------------------------------------

   // 데이터 조회 / 사용예시 : getRedis("홍길동")
  getRedis: async (key) => {
    return await redisClient.get(key);
  },
  

----------------------------------------

 // 데이터 해시로 저장
  addRedisToHash: async (key, val) => {
    return await redisClient.hset(key, ...Object.entries(val).flat());
  },
  
----------------------------------------

 // 데이터 키,필드,벨류 모두 저장
  setByVal: async (key, field, val) => {
    return await redisClient.hset(key, field, val);
  },
  
 ----------------------------------------
 
    // 해시의 벨류값을 덮어씌우는 함수 
  update : async (key, fiedl, val) => {
    // 목록저장
    await redisClient.hset(`room:${key}`, fiedl, JSON.stringify(val));
    console.log(`${key}에 저장되었습니다.`);
  },
  
 ----------------------------------------
 
  //키-필드 를 사용하여 해당 벨류 가져오기
    getByVal: async (key, field) => {

    const roomValue = await redisClient.hget(key, val);

    if (roomValue === null) {
      console.error(`해당 키에 대한 정보가 없습니다: ${key}`);
      return null;
    }
    return roomValue;
  },
  
  ----------------------------------------
  
    // 이름에 해당하는 모든 키 가져오기
  getNameKeys: async (pattern) => {
    const keys = [];
    let cursor = '0'; // SCAN의 커서 초기값

    do {
      // SCAN을 사용하여 키를 가져옴
      //cursor = 다음 스캔 시작 위치 , 처음호출시 0
      //MATCH pattern = 특정 패턴에 따른 키 필터링 , 예시:room:*
      //COUNT 100 = 한번의 스캔에서 반환할 키의 대략적인 수 지정
      const result = await redisClient.scan(cursor, 'MATCH', pattern, 'COUNT', 100);
      cursor = result[0]; // 다음 커서 업데이트
      keys.push(...result[1]); // 가져온 키를 배열에 추가
    } while (cursor !== '0'); // 커서가 0이 아닐 때까지 반복

    return keys; // 모든 키 반환
  },
  
  ----------------------------------------
  
    // 필드 값으로 키 찾기
  findKeyToField: async (keys, field, fieldvalue) => {
    for (const key of keys) {
      const value = await redisClient.hget(key, field);
      if (value == fieldvalue) {
        return key;
      }
    }
    return null;
  },
  
  ----------------------------------------
  
  // 해당키값의 모든 필드 가져오기
  getAllFieldsFromHash: async (key) => {
    const hashData = await redisClient.hgetall(key); // 모든 필드와 값을 가져옴

    if (!hashData) {
      console.error(`해시가 존재하지 않습니다: ${key}`);
      return null; // 해시가 존재하지 않을 때 null 반환
    }

    return hashData; // 해시의 모든 필드와 값을 반환
  },
  
  ----------------------------------------
  
    // 키값으로 레디스 데이터 삭제하기
  delRedisByKey: async (key) => {
    try {
      await redisClient.del(key);
    } catch (err) {
      console.error(err);
    }
  },
  
  ----------------------------------------
  
  //redis에 있는 모든 데이터 삭제하기
   allDateDel: async () => {
    await redisClient.flushall();
  },​

 

'Redis' 카테고리의 다른 글

redis 기본 명령어 /사용법 / 설정 / 전략  (2) 2024.11.18