Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Redis

Redis, Redis Failover, Consistent Hashing, Commands, Failures

  • Inicia sesión para ver los comentarios

Redis

  1. 1. 우아한 Redis charsyam@naver.com
  2. 2. 목차 ● Redis 소개 ● 왜 Collection이 중요한가? ● Redis Collections ● Redis 운영 ● Redis 데이터 분산 ● Redis Failover
  3. 3. 오늘 발표에서 다루지 않는 것들 ● Redis Persistence(RDB, AOF) ● Redis Pub/Sub ● Redis Stream ● 확률적 자료구조 ○ Hyperloglog ● Redis Module
  4. 4. Redis 소개 ● In-Memory Data Structure Store ● Open Source(BSD 3 License) ● Support data structures ○ Strings, set, sorted-set, hashes, list ○ Hyperloglog, bitmap, geospatial index ○ Stream ● Only 1 Committer
  5. 5. Redis 를 소개하기 전에 Cache 먼저~~~
  6. 6. Cache 가 무엇일까요?
  7. 7. Cache의 정의 ● Cache 는 나중에 요청올 결과를 미리 저장해두었다가 빠르게 서비스를 해주는 것을 의미
  8. 8. Factorial
  9. 9. Factorial 의 계산 ● 10! = 10 * 9! = 10 * 9 * 8! = 10 * 9 * 8 * 7! ● 19! = 19 * 18 * 17 * 16 * 15 * 14 * 13 * 12 * 11 * 10! ● 팩토리얼 숫자가 크다면? ○ 20880!, 20881! 를 매번 계산해야 한다면?
  10. 10. 20880! 를 계산해 두고 어딘가에 저장해 뒀다면 20881! 계산은 금방!!!!
  11. 11. 접근 속도가 다를 때...
  12. 12. CPU Cache
  13. 13. 어디서 많이 사용하나요?
  14. 14. 아주 추상적인 웹서비스 구조 Client Web Server DB DB 안에는 많은 데이터들이 있고, 이 때 주로 디스크에 내용이 저장되게 됩니다.
  15. 15. 파레토 법칙
  16. 16. 전체 요청의 80%는 20%의 사용자
  17. 17. Cache 구조 #1 - Look aside Cache Client Web Server DB Memory Cache를 이용하게 되면 훨씬 더 빠른 속도로 서비스가 가능합니다. Cache 1. Web Server 는 데이터가 존재하는지 Cache를 먼저 확인 2. Cache에 데이터가 있으면 Cache에서 가져온다. 3. Cache에 데이터가 없다면 DB에서 읽어온다. 4. DB에서 읽어온 데이터를 Cache에 다시 저장한다.
  18. 18. Cache 구조 #2 - Write Back Client Web Server DB Memory Cache를 이용하게 되면 훨씬 더 빠른 속도로 서비스가 가능합니다. Cache 1. Web Server 는 모든 데이터를 Cache에만 저장 2. Cache에 특정 시간동안의 데이터가 저장 3. Cache에 있는 데이터를 DB에 저장한다. 4. DB에 저장된 데이터를 삭제한다.
  19. 19. 왜 Collection 이 중요한가? ● 개발의 편의성 ● 개발의 난이도
  20. 20. 개발의 편의성 랭킹 서버를 직접 구현한다면?
  21. 21. 개발의 편의성 ● 가장 간단한 방법 ○ DB에 유저의 Score를 저장하고 Score 로 order by로 정렬 후 읽어오기.
  22. 22. 개발의 편의성 ● 가장 간단한 방법 ○ DB에 유저의 Score를 저장하고 Score 로 order by로 정렬 후 읽어오기. ○ 개수가 많아지면 속도에 문제가 발생할 수 있음. ■ 결국은 디스크를 사용하므로
  23. 23. 개발의 편의성 ● In-Memory 기준으로 랭킹 서버의 구현이 필요함. ○ 능력자면, 금방 만드실....(?)
  24. 24. 개발의 편의성 ● Redis의 Sorted Set을 이용하면, 랭킹을 구현 할 수 있음. ○ 덤으로, Replication도 가능… ○ 다만 가져다 쓰면 거기의 한계에 종속적이 됨. ■ 랭킹에 저장해야할 id가 1개당 100byte라고 했을때 ● 10명 1K ● 10000명 1M ● 10000000명 1G ● 10000000000 명 1TB
  25. 25. 개발의 난이도 친구 리스트를 관리해봅시다.
  26. 26. 개발의 난이도 ● 친구 리스트를 KEY/VALUE 형태로 저장해야 한다면? ○ 현재 유저 123의 친구 Key는 friends:123, 현재 친구 A가 있는 중 T1(친구 B를 추가) ● 친구 리스트 friends:123 을 읽는다. ● friends:123 의 끝에 친구 B를 추가한다. ● 해당 값을 friend:123 에 저장한다. T1(친구 C를 추가) ● 친구 리스트 friends:123 을 읽는다. ● friends:123 의 끝에 친구 C를 추가한다. ● 해당 값을 friend:123 에 저장한다.
  27. 27. 개발의 난이도 ● 어떤 문제가 발생할 수 있을까요? T1(친구 B를 추가) ● 친구 리스트 friends:123 을 읽는다. ● friends:123 의 끝에 친구 B를 추가한다. ● 해당 값을 friend:123 에 저장한다. T1(친구 C를 추가) ● 친구 리스트 friends:123 을 읽는다. ● friends:123 의 끝에 친구 C를 추가한다. ● 해당 값을 friend:123 에 저장한다.
  28. 28. 개발의 난이도 ● 어떤 문제가 발생할 수 있을까요? 시간순서 T1(친구 B 추가) T2(친구 C 추가) 최종상태 1 friends:123 읽기 A 2 친구 B 추가 A 3 friends:123 쓰기 A, B 4 friends:123 읽기 A, B 5 친구 C 추가 A, B 6 friends:123 쓰기 A, B, C
  29. 29. 개발의 난이도 ● Race Condition 시간순서 T1(친구 B 추가) T2(친구 C 추가) 최종상태 1 friends:123 읽기 A 2 friends:123 읽기 A 3 친구 B 추가 A 4 친구 C 추가 A 5 friends:123 쓰기 A, B 6 friends:123 쓰기 A, C
  30. 30. 개발의 난이도 ● Race Condition 시간순서 T1(친구 B 추가) T2(친구 C 추가) 최종상태 1 friends:123 읽기 A 2 friends:123 읽기 A 3 친구 B 추가 A 4 친구 C 추가 A 5 friends:123 쓰기 A, C 6 friends:123 쓰기 A, B
  31. 31. 개발의 난이도 ● Redis의 경우는 자료구조가 Atomic 하기 때문에, 해당 Race Condition 을 피할 수 있습니다. ○ 그래도 잘못짜면 발생함.
  32. 32. 왜 Collection 이 중요한가? ● 외부의 Collection을 잘 이용하는 것으로, 여러가지 개발 시간을 단축시키고, 문제를 줄여줄 수 있기 때문에 Collection 이 중요.
  33. 33. Redis는 실행했는데 어디에 써야 하죠?
  34. 34. Redis 사용 처 ● Remote Data Store ○ A서버, B서버, C서버에서 데이터를 공유하고 싶을때 ● 한대에서만 필요한다면, 전역 변수를 쓰면 되지 않을까? ○ Redis 자체가 Atomic을 보장해준다.(싱글 스레드라…) ● 주로 많이 쓰는 곳들 ○ 인증 토큰 등을 저장(Strings 또는 hash) ○ Ranking 보드로 사용(Sorted Set) ○ 유저 API Limit ○ 잡 큐(list)
  35. 35. Redis Collections
  36. 36. Redis Collections ● Strings ● List ● Set ● Sorted Set ● Hash
  37. 37. Strings Key/Value
  38. 38. Strings - 단일 Key ● 기본 사용법 ○ Set <key> <value> ○ Get <key> ● Set token:1234567 abcdefghijklmn ● Get token:1234567
  39. 39. Strings - 멀티 Key ● 기본 사용법 ○ mset <key1> <value1> <key2> <value2> …… <keyN> <valueN> ○ mget <key1> <key2> …… <keyN> ● mset token:1234567 abcdefghijklmn email:1234567 charsyam@naver.com ● mget token:1234567 email:1234567
  40. 40. Strings - 간단한 SQL을 대체한다면? ● Insert into users(name, email) values(‘charsyam’, ‘charsyam@naver.com’); ● Using Set ○ Set name:charsyam charsyam ○ Set email:charsyam charsyam@naver.com ● Using mset ○ Mset name:charsyam charsyam email:charsyam charsyam@naver.com
  41. 41. List
  42. 42. List : insert ● 기본 사용법 ○ Lpush <key> <A> ■ Key: (A) ○ Rpush <key> <B> ■ Key: (A, B) ○ Lpush <key> <C> ■ Key: (C, A, B) ○ Rpush <key> <D, A> ■ Key: (C, A, B, D, A)
  43. 43. List : pop ● 기본 사용법 ○ Key: (C, A, B, D, A) ○ LPOP <key> ■ Pop C, Key: (A, B, D, A) ○ RPOP <key> ■ Pop A, Key: (A, B, D) ○ RPOP <key> ■ Pop D, Key: (A, B)
  44. 44. List : lpop, blpop, rpop, brpop ● 기본 사용법 ○ Key: () ○ LPOP <key> ■ No Data ○ BLPOP <key> ■ 누가 데이터를 Push 하기 전까지 대기
  45. 45. Set
  46. 46. Set : 데이터가 있는지 없는지만 체크하는 용도 ● 기본 사용법 ○ SADD <Key> <Value> ■ Value가 이미 Key에 있으면 추가되지 않는다. ○ SMEMBERS <Key> ■ 모든 Value를 돌려좀 ○ SISMEMBER <key> <value> ■ value가 존재하면 1, 없으면 0 ● 특정 유저를 Follow 하는 목록을 저장해둔다면
  47. 47. Sorted Sets
  48. 48. Sorted Sets : 랭킹에 따라서 순서가 바뀌길 바란다면 ● 기본 사용법 ○ ZADD <Key> <Score> <Value> ■ Value가 이미 Key에 있으면 해당 Score로 변경된다. ○ ZRANGE <Key> <StartIndex> <EndIndex> ■ 해당 Index 범위 값을 모두 돌려줌 ■ Zrange testkey 0 -1 ● 모든 범위를 가져옴. ● 유저 랭킹 보드로 사용할 수 있음. ● Sorted sets의 score 는 double 타입이기 때문에, 값이 정확하지 않을 수 있다. ○ 컴퓨터에서는 실수가 표현할 수 없는 정수값들이 존재.
  49. 49. Sorted Sets - 정렬이 필요한 값이 필요하다면? ● select * from rank order by score limit 50, 20; ○ zrange rank 50 70 ● Select * from rank order by score desc limit 50, 20; ○ Zrevrange rank 50 70
  50. 50. Sorted Sets - Score 기준으로 뽑고 싶다면? ● select * from rank where score >= 70 and score < 100; ○ zrangebyscore rank 70 100 ● Select * from rank where score > 70; ○ Zrangebyscore rank (70 +inf
  51. 51. Hash
  52. 52. Hash: Key 밑에 sub key가 존재 ● 기본 사용법 ○ Hmset <key> <subkey1> <value1> <subkey2> <value2> ○ Hgetall <key> ■ 해당 key의 모든 subkey와 value를 가져옴 ○ Hget <key> <subkey> ○ Hmget <key> <subkey1> <subkey2> …… <subkeyN>
  53. 53. Hash - 간단한 SQL을 대체한다면? ● Insert into users(name, email) values(‘charsyam’, ‘charsyam@naver.com’); ● hmset charsyam name charsyam email charsyam@naver.com
  54. 54. Collection 주의 사항
  55. 55. Collection 주의 사항 ● 하나의 컬렉션에 너무 많은 아이템을 담으면 좋지 않음 ○ 10000개 이하 몇천개 수준으로 유지하는게 좋음. ● Expire는 Collection의 item 개별로 걸리지 않고 전체 Collection에 대해서만 걸림 ○ 즉 해당 10000개의 아이템을 가진 Collection에 expire가 걸려있다면 그 시간 후에 10000개의 아이템이 모두 삭제.
  56. 56. Redis 운영
  57. 57. Redis 운영 ● 메모리 관리를 잘하자. ● O(N) 관련 명령어는 주의하자. ● Replication ● 권장 설정 Tip
  58. 58. 메모리 관리를 잘하자!
  59. 59. 메모리 관리 ● Redis 는 In-Memory Data Store. ● Physical Memory 이상을 사용하면 문제가 발생 ○ Swap 이 있다면 Swap 사용으로 해당 메모리 Page 접근시 마다 늦어짐. ○ Swap이 없다면? ● Maxmemory를 설정하더라도 이보다 더 사용할 가능성이 큼. ● RSS 값을 모니터링 해야함.
  60. 60. 메모리 관리 ● 많은 업체가 현재 메모리를 사용해서 Swap을 쓰고 있다는 것을 모를때가 많음(T.T)
  61. 61. 메모리 관리 ● 큰 메모리를 사용하는 instance 하나보다는 적은 메모리를 사용하는 instance 여러개가 안전함. ● CPU 4 Core, 32GB Memory 24 GB Instance 8 GB Instance 8 GB Instance 8 GB Instance
  62. 62. 메모리 관리 ● Redis는 메모리 파편화가 발생할 수 있음. 4.x 대 부터 메모리 파현화를 줄이도록 jemlloc에 힌트를 주는 기능이 들어갔으나, jemalloc 버전에 따라서 다르게 동작할 수 있음. ● 3.x대 버전의 경우 ○ 실제 used memory는 2GB로 보고가 되지만 11GB의 RSS를 사용하는 경우가 자주 발생 ● 다양한 사이즈를 가지는 데이터 보다는 유사한 크기의 데이터를 가지는 경우가 유리.
  63. 63. 메모리가 부족할 때는? ● Cache is Cash!!! ○ 좀 더 메모리 많은 장비로 Migration. ○ 메모리가 빡빡하면 Migration 중에 문제가 발생할수도… ● 있는 데이터 줄이기. ○ 데이터를 일정 수준에서만 사용하도록 특정 데이터를 줄임. ○ 다만 이미 Swap을 사용중이라면, 프로세스를 재시작 해야함.
  64. 64. 메모리를 줄이기 위한 설정 ● 기본적으로 Collection 들은 다음과 같은 자료구조를 사용 ○ Hash -> HashTable을 하나 더 사용 ○ Sorted Set -> Skiplist와 HashTable을 이용. ○ Set -> HashTable 사용 ○ 해당 자료구조들은 메모리를 많이 사용함. ● Ziplist 를 이용하자.
  65. 65. Ziplist 구조 ● In-Memory 특성 상, 적은 개수라면 선형 탐색을 하더라도 빠르다. ● List, hash, sorted set 등을 ziplist로 대체해서 처리를 하는 설정이 존재 ○ hash-max-ziplist-entries, hash-max-ziplist-value ○ list-max-ziplist-size, list-max-ziplist-value ○ zset-max-ziplist-entries, zset-max-ziplist-value zlbytes zltail zllen entry entry ... entry zlend
  66. 66. O(N) 관련 명령어는 주의하자.
  67. 67. O(N) 관련 명령어는 주의하자. ● Redis 는 Single Threaded. ○ 그러면 Redis가 동시에 여러 개의 명령을 처리할 수 있을까? ○ 참고로 단순한 get/set의 경우, 초당 10만 TPS 이상 가능(CPU속도에 영향을 받습니다.)
  68. 68. Redis is Single Threaded. processInputBuffer packet processCommand packet packetpacket Packet 으로 하나의 Command가 완성되면 processCommand 에서 실제로 실행됨
  69. 69. Single Threaded 의 의미 ● Redis 는 Single Threaded. ○ 그러면 Redis가 동시에 여러 개의 명령을 처리할 수 있을까? ○ 참고로 단순한 get/set의 경우, 초당 10만 TPS 이상 가능(물리 서버기준, CPU속도에 영향을 받습니다.)
  70. 70. Single Threaded 의 의미 ● 한번에 하나의 명령만 수행 가능 ○ 그럼 긴 시간이 필요한 명령을 수행하면?
  71. 71. 망합니다!!!
  72. 72. 대표적인 O(N) 명령들 ● KEYS ● FLUSHALL, FLUSHDB ● Delete Collections ● Get All Collections
  73. 73. 대표적인 실수 사례 ● Key가 백만개 이상인데 확인을 위해 KEYS 명령을 사용하는 경우 ○ 모니터링 스크립트가 일초에 한번씩 keys를 호출하는 경우도... ● 아이템이 몇만개 든 hash, sorted set, set에서 모든 데이터를 가져오는 경우 ● 예전의 Spring security oauth RedisTokenStore
  74. 74. KEYS 는 어떻게 대체할 것인가? ● scan 명령을 사용하는 것으로 하나의 긴 명령을 짧은 여러번의 명령으로 바꿀 수 있다. redis 127.0.0.1:6379> scan 0 1) "17" 2) 1) "key:12" 2) "key:8" 3) "key:4" redis 127.0.0.1:6379> scan 17 1) "0" 2) 1) "key:5" 2) "key:18" 3) "key:0" 7) "key:6" 8) "key:9" 9) "key:11"
  75. 75. Collection의 모든 item을 가져와야 할 때? ● Collection의 일부만 가져오거나… ○ Sorted Set ● 큰 Collection을 작은 여러개의 Collection으로 나눠서 저장 ○ Userranks -> Userrank1, Userrank2, Userrank3 ○ 하나당 몇천개 안쪽으로 저장하는게 좋음.
  76. 76. Spring security oauth RedisTokenStore 이슈 ● Access Token의 저장을 List(O(N)) 자료구조를 통해서 이루어짐. ○ 검색, 삭제시에 모든 item을 매번 찾아봐야 함. ■ 100만개 쯤 되면 전체 성능에 영향을 줌. ○ 현재는 Set(O(1))을 이용해서 검색, 삭제를 하도록 수정되어있음.
  77. 77. Spring security oauth RedisTokenStore 이슈 ● https://charsyam.wordpress.com/2018/05/11/입-개발-spring-security-oauth의-redistokenstore의-사용은-서비스에- 적합하지-않/
  78. 78. Redis Replication
  79. 79. Redis Replication ● Async Replication ○ Replication Lag 이 발생할 수 있다. ● “Replicaof’(>= 5.0.0) or ‘slaveof’ 명령으로 설정 가능 ○ Replicaof hostname port ● DBMS로 보면 statement replication가 유사
  80. 80. Redis Replication ● Replication 설정 과정 ○ Secondary에 replicaof or slaveof 명령을 전달 ○ Secondary는 Primary에 sync 명령 전달 ○ Primary는 현재 메모리 상태를 저장하기 위해 ■ Fork ○ Fork 한 프로세서는 현재 메모리 정보를 disk에 dump ○ 해당 정보를 secondary 에 전달 ○ Fork 이후의 데이터를 secondary에 계속 전달
  81. 81. Redis Replication 시 주의할 점 ● Replication 과정에서 fork 가 발생하므로 메모리 부족이 발생할 수 있다. ● Redis-cli --rdb 명령은 현재 상태의 메모리 스냅샷을 가져오므로 같은 문제를 발생시킴 ● AWS나 클라우드의 Redis는 좀 다르게 구현되어서 좀더 해당 부분이 안정적.
  82. 82. Redis Replication 시 주의할 점 ● 많은 대수의 Redis 서버가 Replica를 두고 있다면 ○ 네트웍 이슈나, 사람의 작업으로 동시에 replication이 재시도 되도록 하면 문제가 발생할 수 있음. ○ ex) 같은 네트웍안에서 30GB를 쓰는 Redis Master 100대 정도가 리플리케이션을 동시에 재시작하면 어떤 일이 벌어질 수 있을까?
  83. 83. 권장 설정 Tip(redis.conf)
  84. 84. redis.conf 권장 설정 Tip ● Maxclient 설정 50000 ● RDB/AOF 설정 off ● 특정 commands disable ○ Keys ○ AWS의 ElasticCache는 이미 하고 있음. ● 전체 장애의 90% 이상이 KEYS와 SAVE 설정을 사용해서 발생. ● 적절한 ziplist 설정
  85. 85. Redis 데이터 분산
  86. 86. Redis 데이터 분산 ● 데이터의 특성에 따라서 선택할 수 있는 방법이 달라진다. ○ Cache 일때는 우아한 Redis(정말?) ○ Persistent 해야하면 안 우아한 Redis!!! ■ Open the hellgate!!!
  87. 87. 데이터 분산 방법
  88. 88. 데이터 분산 방법 ● Application ○ Consistent Hashing ■ twemproxy 를 사용하는 방법으로 쉽게 사용 가능 ○ Sharding ● Redis Cluster
  89. 89. Consistent Hashing
  90. 90. WHY?
  91. 91. There was data In the beginning.
  92. 92. 1 2 3 4 5 6 7 89
  93. 93. How do you distribute data pairly into 3 servers? Considering the future.
  94. 94. 1 2 3 4 5 6 7 8 9 Sequence
  95. 95. 1 2 3 4 5 6 7 8 9 Modular
  96. 96. If you add one server, or remove one server What happened?
  97. 97. 1 2 3 4 5 6 Add one server for Sequence 7 8 9
  98. 98. Add one server for Modular 1 2 3 4 5 6 7 8 9
  99. 99. How do you redistribute these data?
  100. 100. Redistribute by Modular 1 2 3 4 5 6 7 8 9
  101. 101. Most of data is redistributed!
  102. 102. Redistribution is Burden.
  103. 103. What is a good way to reduce redistribution?
  104. 104. Consistent Hashing Can Do!!!
  105. 105. Consistent Hashing redistribute only N/K data N = data size K = servers
  106. 106. Key Concept is Hash
  107. 107. What is main concept of hash
  108. 108. If you use The same hash function? The result is always the same.
  109. 109. hash(“abc”) = 1 hash(“abc1”) = 2 hash(“abc”) = 1
  110. 110. You have 3 servers. 10.0.1.1 10.0.1.2 10.0.1.3
  111. 111. There is a hash function. y = hash(x)
  112. 112. You hash 3 servers hash(“10.0.1.1”) = 100 hash(“10.0.1.2”) = 400 hash(“10.0.1.3”) = 700 Just Giving server address as key
  113. 113. Just define a rule. We will store a key in hash(key) is higher and the nearest one.
  114. 114. hash(key) Hash value hash(“10.0.1.1”) 100 hash(“10.0.1.2”) 400 hash(“10.0.1.3”) 700
  115. 115. There is key “redis” hash(“redis”) = 200 Where we store it?
  116. 116. hash(key) Hash value hash(“10.0.1.1”) 100 hash(“redis”) 200 in hash(“10.0.1.2”) hash(“10.0.1.2”) 400 hash(“10.0.1.3”) 700
  117. 117. There is key “charsyam” hash(“charsyam”) = 450 Where we store it?
  118. 118. hash(key) Hash value hash(“10.0.1.1”) 100 hash(“redis”) 200 in hash(“10.0.1.2”) hash(“10.0.1.2”) 400 hash(“charsyam”) 450 in hash(“10.0.1.3”) hash(“10.0.1.3”) 700
  119. 119. There is key “udemy” hash(“udemy”) = 50 Where we store it?
  120. 120. hash(key) Hash value hash(“udemy”) 50 in hash(“10.0.1.1”) hash(“10.0.1.1”) 100 hash(“redis”) 200 in hash(“10.0.1.2”) hash(“10.0.1.2”) 400 hash(“charsyam”) 450 in hash(“10.0.1.3”) hash(“10.0.1.3”) 700
  121. 121. There is key “web” hash(“web”) = 1000 Where we store it?
  122. 122. There is no server has higher hash value 1000. Where we can store it?
  123. 123. Think it is Circle
  124. 124. hash(key) Hash value hash(“udemy”) 50 in hash(“10.0.1.1”) hash(“10.0.1.1”) 100 hash(“redis”) 200 in hash(“10.0.1.2”) hash(“10.0.1.2”) 400 hash(“charsyam”) 450 in hash(“10.0.1.3”) hash(“10.0.1.3”) 700 hash(“web”) 1000 in hash(“10.0.1.1”)
  125. 125. Key “web” is stored in First Server.
  126. 126. If we add new server It is “10.0.1.4”. And hash(“10.0.1.4”) = 500
  127. 127. hash(key) Hash value hash(“udemy”) 50 in hash(“10.0.1.1”) hash(“10.0.1.1”) 100 hash(“redis”) 200 in hash(“10.0.1.2”) hash(“10.0.1.2”) 400 DELETED hash(“charsyam”) 450 hash(“10.0.1.4”) 500 hash(“10.0.1.3”) 700 hash(“web”) 1000 in hash(“10.0.1.1”)
  128. 128. After adding “10.0.1.4” Key “charsyam” is missing
  129. 129. But other keys are never changed.
  130. 130. You can still find key “udemy” in “10.0.1.1”
  131. 131. There is key “charsyam” hash(“charsyam”) = 450 Where we store it?
  132. 132. hash(key) Hash value hash(“udemy”) 50 in hash(“10.0.1.1”) hash(“10.0.1.1”) 100 hash(“redis”) 200 in hash(“10.0.1.2”) hash(“10.0.1.2”) 400 hash(“charsyam”) 450 in hash(“10.0.1.4”) hash(“10.0.1.4”) 500 hash(“10.0.1.3”) 700 hash(“web”) 1000 in hash(“10.0.1.1”)
  133. 133. A Add A Server
  134. 134. A B Add B Server
  135. 135. A BC Add C Server
  136. 136. A BC Add Key 1 1
  137. 137. A BC Add Key 2 1 2
  138. 138. A BC Add Key 3 1 2 3
  139. 139. A BC Add Key 4 1 2 3 4
  140. 140. A BC Add Key 5 1 2 3 4 5
  141. 141. A C Fail B Server 2 3 4 5
  142. 142. A C Add Key 1 2 3 4 5 1
  143. 143. 서버 주소를 해싱하는 것보다 Nickname으로 해싱 하는 것이 더 변동이 적음
  144. 144. Sharding
  145. 145. 데이터를 어떻게 나눌것인가? 데이터를 어떻게 찾을것인가?
  146. 146. 하나의 데이터를 모든 서버에서 찾아야 하면?
  147. 147. 상황마다 샤딩 전략이 달라짐
  148. 148. Range ● 그냥 특정 Range를 정의하고 해당 Range에 속하면 거기에 저장. ○ Key 500 은 어디에 저장되어야 할까? 1~1000 1001~2000 2001~3000
  149. 149. Range ● 특정 Range 서버에만 부하가 몰릴 가능성이 높다. ○ 활동량이 많은 유저가 많은 서버는? ■ 이벤트 때문에 가입한 유저들.
  150. 150. Modular ● N % K 로 서버의 데이터를 결정 ● Range 보다 데이터를 균등하게 분배할 가능성이 높다. 1 3 5 7 2 4 6 8
  151. 151. Modular ● 서버 한대가 추가될 때 재분배 양이 많아진다. 1 4 7 2 5 8 3 6
  152. 152. Indexed ● 해당 Key가 어디에 저장되어야 할 관리 서버가 따로 존재 1000 10001 1 200 Index Server 2 3 1. Where is 2? 2. 2 is on Server 3 client
  153. 153. Redis Cluster
  154. 154. Redis Cluster ● Hash 기반으로 Slot 16384 로 구분 ○ Hash 알고리즘은 CRC16을 사용 ○ Slot = crc16(key) % 16384 ○ Key가 Key{hashkey} 패턴이면 실제 crc16에 hashkey가 사용된다. ○ 특정 Redis 서버는 이 slot range를 가지고 있고, 데이터 migration은 이 slot 단위의 데이터를 다른 서버로 전달하게 된다.(migrateCommand 이용)
  155. 155. Redis Cluster Primary #1 Primary #2 Primary #3 Secondary #1 Secondary #2 Secondary #3 Client
  156. 156. Redis Cluster Primary #1 Primary #2 Primary #3 Secondary #1 Primary #2 Secondary #3 Client
  157. 157. Redis Cluster Primary #1 Primary #2 Primary #3 Secondary #1 Secondary #2 Secondary #3 Client Slot: 0~5555 Slot: 5556~11000 Slot: 11001~16383 Set Slot0_key abc
  158. 158. Redis Cluster Primary #1 Primary #2 Primary #3 Secondary #1 Secondary #2 Secondary #3 Client Slot: 0~5555 Slot: 5556~11000 Slot: 11001~16383 +OK
  159. 159. Redis Cluster Primary #1 Primary #2 Primary #3 Secondary #1 Secondary #2 Secondary #3 Client Slot: 0~5555 Slot: 5556~11000 Slot: 11001~16383 Set Slot5506_key abc
  160. 160. Redis Cluster Primary #1 Primary #2 Primary #3 Secondary #1 Secondary #2 Secondary #3 Client Slot: 0~5555 Slot: 5556~11000 Slot: 11001~16383 -MOVED Primary #2
  161. 161. Redis Cluster의 장점/단점 ● 장점 ○ 자체적인 Primary, Secondary Failover. ○ Slot 단위의 데이터 관리. ● 단점 ○ 메모리 사용량이 더 많음 ○ Migration 자체는 관리자가 시점을 결정해야 함. ○ Library 구현이 필요함.
  162. 162. Redis Failover
  163. 163. Redis Failover ● Coordinator 기반 Failover ● VIP/DNS 기반 Failover ● Redis Cluster 의 사용
  164. 164. Coordinator 기반 ● Zookeeper, etcd, consul 등의 Coordinator 사용 API Server Redis #1 : P Redis #2 : S Coordinator: current Redis is Redis #1 Health Checker
  165. 165. Coordinator 기반 API Server Redis #1 : P Redis #2 : S Coordinator: current Redis is Redis #1 Health Checker
  166. 166. Coordinator 기반 API Server Redis #1 : P Redis #2 : P Coordinator: current Redis is Redis #1 Health Checker Health Checker는 Redis #2를 Primary 로 승격시킨다.
  167. 167. Coordinator 기반 API Server Redis #1 : P Redis #2 : P Coordinator: current Redis is Redis #2 Health Checker Health Checker는 Redis #2를 Primary 로 승격시킨다. Health Checker는 Coordinator에 current Redis가 Redis #2라고 업데이트 한다.
  168. 168. Coordinator 기반 API Server Redis #1 : P Redis #2 : P Coordinator: current Redis is Redis #2 Health Checker Health Checker는 Redis #2를 Primary 로 승격시킨다. Health Checker는 Coordinator에 current Redis가 Redis #2라고 업데이트 한다. Coordinator는 API Server에 current Redis 가 변경되었다고 알려준다.
  169. 169. Coordinator 기반 ● Coordinator 기반으로 설정을 관리한다면 동일한 방식으로 관리가 가능. ● 해당 기능을 이용하도록 개발이 필요하다.
  170. 170. VIP 기반 API Server Redis #1 : P Redis #2 : S Health Checker VIP: 10.0.1.1. API Server는 10.0.1.1로만 접속
  171. 171. VIP 기반 API Server Redis #1 : P Redis #2 : S Health Checker VIP: 10.0.1.1. API Server는 10.0.1.1로만 접속
  172. 172. VIP 기반 API Server Redis #1 : P Redis #2 : P Health Checker VIP: 10.0.1.1. API Server는 10.0.1.1로만 접속 Health Checker는 Redis #2를 Primary 로 승격시킨다.
  173. 173. VIP 기반 API Server Redis #1 : P Redis #2 : P Health Checker VIP: 10.0.1.1. API Server는 10.0.1.1로만 접속 Health Checker는 Redis #2를 Primary 로 승격시킨다. Health Checker는 VIP 10.0.1.1 을 Redis #2 로 할당한다.
  174. 174. VIP 기반 API Server Redis #1 : P Redis #2 : P Health Checker VIP: 10.0.1.1. API Server는 10.0.1.1로만 접속 Health Checker는 Redis #2를 Primary 로 승격시킨다. Health Checker는 VIP 10.0.1.1 을 Redis #2 로 할당한다. Health Checker는 Redis #1에 있던 기존 연결을 모두 끊어준다.(클라이언트의 재접속 유도)
  175. 175. DNS 기반 API Server Redis #1 : P Redis #2 : S Health Checker DNS: redis-primary.svc.io API Server는 redis-primary.svc.io로만 접속
  176. 176. DNS 기반 API Server Redis #1 : P Redis #2 : S Health Checker DNS: redis-primary.svc.io API Server는 redis-primary.svc.io로만 접속
  177. 177. DNS 기반 API Server Redis #1 : P Redis #2 : P Health Checker DNS: redis-primary.svc.io API Server는 redis-primary.svc.io로만 접속 Health Checker는 Redis #2를 Primary 로 승격시킨다.
  178. 178. DNS 기반 API Server Redis #1 : P Redis #2 : P Health Checker DNS: redis-primary.svc.io API Server는 redis-primary.svc.io로만 접속 Health Checker는 Redis #2를 Primary 로 승격시킨다.
  179. 179. DNS 기반 API Server Redis #1 : P Redis #2 : P Health Checker DNS: redis-primary.svc.io API Server는 redis-primary.svc.io로만 접속 Health Checker는 Redis #2를 Primary 로 승격시킨다. Health Checker는 DNS: redis-primary.svc.io 을 Redis #2 로 할당한다.
  180. 180. DNS 기반 API Server Redis #1 : P Redis #2 : P Health Checker DNS: redis-primary.svc.io API Server는 redis-primary.svc.io로만 접속 Health Checker는 Redis #2를 Primary 로 승격시킨다. Health Checker는 DNS: redis-primary.svc.io 을 Redis #2 로 할당한다. Health Checker는 Redis #1에 있던 기존 연결을 모두 끊어준다.(클라이언트의 재접속 유도)
  181. 181. VIP/DNS 기반 ● 클라이언트에 추가적인 구현이 필요없다. ● VIP 기반은 외부로 서비스를 제공해야 하는 서비스 업자에 유리 (예를 들어 클라우드 업체) ● DNS 기반은 DNS Cache TTL을 관리해야 함. ○ 사용하는 언어별 DNS 캐싱 정책을 잘 알아야 함 ○ 툴에 따라서 한번 가져온 DNS 정보를 다시 호출 하지 않는 경우도 존재
  182. 182. Monitoring
  183. 183. Monitoring Factor ● Redis Info를 통한 정보 ○ RSS ○ Used Memory ○ Connection 수 ○ 초당 처리 요청 수 ● System ○ CPU ○ Disk ○ Network rx/tx
  184. 184. CPU가 100%를 칠 경우 ● 처리량이 매우 많다면? ○ 좀 더 CPU 성능이 좋은 서버로 이전 ○ 실제 CPU 성능에 영향을 받음 ■ 그러나 단순 get/set은 초당 10만 이상 처리가능 ● O(N) 계열의 특정 명령이 많은 경우. ○ Monitor 명령을 통해 특정 패턴을 파악하는 것이 필요 ○ Monitor 잘못쓰면 부하로 해당 서버에 더 큰 문제를 일으킬 수도 있음.(짧게 쓰는게 좋음)
  185. 185. 결론
  186. 186. 결론 ● 기본적으로 Redis는 매우 좋은 툴 ● 그러나 메모리를 빡빡하게 쓸 경우, 관리하기가 어려움 ○ 32기가 장비라면 24기가 이상 사용하면 장비 증설을 고려하는 것이 좋음. ○ Write가 Heavy 할 때는 migration도 매우 주의해야함. ● Client-output-buffer-limit 설정이 필요.
  187. 187. Redis as Cache ● Cache 일 경우는 문제가 적게 발생 ○ Redis 가 문제가 있을 때 DB등의 부하가 어느정도 증가하는 지 확인 필요. ○ Consistent Hashing도 실제 부하를 아주 균등하게 나누지는 않음. Adaptive Consistent Hashing 을 이용해 볼 수도 있음.
  188. 188. Redis as Persistent Store ● Persistent Store의 경우 ○ 무조건 Primary/Secondary 구조로 구성이 필요함 ○ 메모리를 절대로 빡빡하게 사용하면 안됨. ■ 정기적인 migration이 필요. ■ 가능하면 자동화 툴 을 만들어서 이용 ○ RDB/AOF가 필요하다면 Secondary에서만 구동
  189. 189. 감사합니다.

×