Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZK 이벤트를 통한 server list와 ketama hash ring 생성 오류 처리 #219

Open
jhpark816 opened this issue Jan 20, 2022 · 2 comments
Assignees

Comments

@jhpark816
Copy link
Contributor

cache list 변경에 대한 ZK 이벤트를 통해
모든 memcached 구조체의 server list와 ketama hash ring을 갱신한다.
이러한 갱신 작업에서 아래 오류 발생 시의 오류 처리 방식을 수정한다.

  • 발생 가능한 대부분 오류는 메모리 할당 실패이다.
  • 그 외의 오류가 있다면 이는 내부 버그로 대부분 수정하여 해결해야 한다.

메모리 할당 실패로 인해 memcached 구조체의 ketama hash ring 갱신을 실패할 시
이러한 memcached 구조체를 통해 cache server에 요청을 보내는 것은 오동작을 유발시킨다.
발생 빈도가 아주 낮은 오류이지만, 이 경우의 대처 방안으로

  • assert 문으로 응용 process 다운시킬 수 있지만 이는 너무 과도한 정책이며,
  • "invalid ketama hash ring" 의미의 오류 코드를 정의하여 응용에 리턴하는 것이 최적으로 보인다.
    • 캐시 시스템이라는 특성을 가지므로,
    • 캐시를 사용할 수 없는 경우에 응용에게 오류를 리턴하여
    • 응용에서 원본 데이터를 가진 데이터 저장소를 사용할 수 있게 하는 것이 최적이다.
@jhpark816 jhpark816 assigned SuhwanJang and uhm0311 and unassigned SuhwanJang and uhm0311 Jan 20, 2022
@jhpark816
Copy link
Contributor Author

크게 아래 2가지로 구분할 수 있을 것 같습니다.

첫째, 메모리 할당 오류로, invalid server list 가진 memcached 구조체 관리

  • invalid 표시 필요
    • memcached reset 처리 필요
    • 이 경우, server list 변경에 따라 일부 변경된 상태가 clean하게 reset 처리되어야 함.
  • invalid memcached 관리
    • pool에서 가급적 fetch되지 않게 관리
    • 더 이상 사용가능한 memcached 없을 경우에 fetch 허용

둘째, 메모리 할당 오류로, invalid hash ring을 가지는 pool 관리

  • pool 자체를 invalid 표시
  • invalid pool의 관리
    • 응용에서 invalid pool 사용 시에 오류 리턴
    • invalid pool은 주기적으로 ketama hash ring 갱신을 주기적으로(최소 1초 간격은 필요) retry

응용에서 pool이 아닌 single memcached 사용하는 경우도 있습니다.
이 경우는 invalid pool 처리와 동일합니다.

@uhm0311
Copy link
Collaborator

uhm0311 commented Mar 8, 2022

@jhpark816 @SuhwanJang

설계를 공유하고자 합니다.

이 경우, server list 변경에 따라 일부 변경된 상태가 clean하게 reset 처리되어야 함.

  • server list 업데이트 전 old server list를 백업하려고 합니다.
    • 이 때 memcached_clone() 함수를 활용합니다.
    • server list 업데이트 실패 시 실패한 member mc에 대하여 clone 해둔 mc로 바꿉니다.
    • 메모리 부족으로 clone이 실패하는 경우에도 server list 업데이트 실패와 동일한 것으로 처리하려고 합니다.
    • clone이 성공하고 server list 업데이트가 실패하면 member mc를 clone으로 대체하는 과정에서 연결이 끊기는데,
      • 업데이트에 실패한 member mc는 최대한 fetch 되지 않도록 관리할 것이며
      • 업데이트에 실패한 member mc가 fetch 되더라도 정상적인 연산이 불가능할 것이므로 연결이 끊어져도 괜찮을 것으로 봅니다.
  • master mc에 대한 server list 업데이트 실패의 경우 처리도 필요할 것 같습니다.
    • master mc에 대한 server list 업데이트 성공 시에만 member mc에 대한 server list 업데이트를 진행하도록 합니다.
    • master mc는 변경되어선 안되므로 이 때는 clone 동작을 하지 않습니다.
    • server list 업데이트가 실패한다면 아래의 기존 처리대로 log로 오류가 있음을 응용에 알립니다. 이 코드에서 error 값이 무엇인지 함께 출력하면 좋을 것 같습니다.
      if (error == MEMCACHED_SUCCESS) {
      ZOO_LOG_WARN(("CACHE_LIST=UPDATED, to %s, cache_servers=%d in %d ms",
      arcus->zk.ensemble_list, mc->number_of_hosts, msec));
      } else {
      ZOO_LOG_WARN(("CACHE_LIST=UPDATE_FAIL in %d ms", msec));
      }

invalid pool은 주기적으로 ketama hash ring 갱신을 주기적으로(최소 1초 간격은 필요) retry

  • 두 가지 경우가 있습니다.
    • 최초에 master mc update 시 오류가 나는 경우에는 위의 기존 처리대로 log로 오류가 있음을 응용에 알립니다.
    • 이후에 master mc update 시 오류가 나는 경우에는, 주기적인 retry를 위해 다음의 의사 코드를 수행하는 thread를 생성하려고 합니다.
      static void *pool_thread_main(void *arg)
      {
        memcached_pool_st *pool= (memcached_pool_st*)arg;
        while (pool->thread_running)
        {
          struct timeval now;
          gettimeofday(&now, NULL);
          if (pool->master->invalid.invalid_hashring
              && pool->master->invalid.last_continuum_failed >= 0
              && now.tv_sec > pool->master->invalid.last_continuum_failed)
          {
            (void)pthread_mutex_lock(&pool->master_lock);
            run_distribution(pool->master);
            (void)pthread_mutex_unlock(&pool->master_lock);
          }
          if (pool->thread_running)
          {
            sleep(1);
          }
        }
      
        return NULL;
      }
    • fetch 수행 시 pool->master->invalid.invalid_hashring == true 이면 rc= MEMCACHED_INVALID_HASHRING을 대입하고 NULL을 반환하려고 합니다.

응용에서 pool이 아닌 single memcached 사용하는 경우도 있습니다.

uhm0311 added a commit to uhm0311/arcus-c-client that referenced this issue Mar 10, 2022
uhm0311 added a commit to uhm0311/arcus-c-client that referenced this issue Mar 11, 2022
uhm0311 added a commit to uhm0311/arcus-c-client that referenced this issue Mar 11, 2022
uhm0311 added a commit to uhm0311/arcus-c-client that referenced this issue Mar 14, 2022
uhm0311 added a commit to uhm0311/arcus-c-client that referenced this issue Mar 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants