Lightweight Directory Access Protocol (LDAP)

LDAP은 한마디로 접근제한 프로토콜이라고 할수 있습니다.

회사에보면 직원들이 있지요 그리고 해당 직원별로 접근이 가능한 정보가 있습니다. 말단직원이 회사의 일급 보안자료를 보게되면 회사가 위험에 빠질수도 있는 문제이기때문이죠. 그리고 인사팀이 전직원 연봉을 관리하는데 그 정보를 다른 직원들이 보게 되는것도 매우 불편한 일이 될테구요. 그러면 이걸 해결하기 위해서 어떻게 하면 좋을까요? 사용자들을 그룹으로 묶어서 관리하고 접속할수 있는 데이타도 접근권한이나 업무성격등으로 묶어서 특정 그룹만이 허용된 데이타에 접근할수 있도록 하면 손쉽게 관리가 되겠죠? 여기서 그룹이라함은 팀만 해당되는 것은 아닙니다. 예를 들어 인사팀의 연봉정보를 예로 들게요. 인사팀이라는 그룹은 해당정보에 접속이 가능해야합니다. 그리고 다른팀 사람들 중에도 연봉정보를 봐야하는 사람들이 있지요. 각 팀의 팀장들은 자기 팀원들의 연봉도 알아야하고, 새로운 사람을 뽑을때 그 사람이 해당연봉에 걸맞는 사람인지도 판단해야하기 때문에 모든 팀의 팀장들은 연봉정보를 알아야합니다. 그리고 회사를 운영하는 임원들도 회사 정책이나 방향을 정할때 연봉정보를 참고할수있기때문에 단순하게 팀으로만 구성해서 권한을 주는 것은 유연성이 없다고 할수 있겠습니다.

LDAP은 모든 서비스를 최대한 작은 단위로 분류해서 다양한 그룹이 다양한 서비스에 다중으로 엮여 효과적으로 접근하도록 구성하는 것이 가능합니다. 그렇게 한번 설정을 해놓으면, 새로 직원을 뽑았을때 그 직원이 속하는 팀과 직급을 가지고 그룹에 추가만 하면 해당 그룹이 가지는 모든 권한을 자동으로 가지게 되므로 개개인을 일일이 설정할필요가 없어서 관리에 용이합니다.

LDAP은 특정 업체가 관리하는 것이 아니라 업계 표준 프로토콜입니다. 그리고 LDAP은 분산된 디렉토리서비스를 관리하고 또는 접속을 제한하는 Internet Protocol (IP) network 단계에서 처리되는 프로토콜입니다.

Domain Directory service는 사용자, 시스템, 네트워크, 서비스 그리고 어플리케이션에 대한 정보를 공유하는 데 대한 허용을 해주는 중요한 역할을 합니다. 마치 디렉토리 서비스가 잘 정돈된 계층적 구조를 가지는 email 디렉토리 같은 서비스를 제공하는것과 같습니다. 비슷하게는 주소와 전화번호가 나열된 전화번호부가 있겠습니다.

LDAP은 승인된 Internet Engineering Task Force (IETF)의 표준이며 Request for Comments(RFCs)를 따릅니다.

일반적으로 LDAP은 중앙에서 사용자의 이름과 비밀번호를 저장하는데 주로 이용됩니다. 이로 인해 수많은 어플리케이션들 간에 권한 관계를 한군데에서 관리하고 접속을 제한할수 있습니다.

LDAP은 X.500표준에서 일부를 발췌하여 심플하게 만든 표준이기 때문에 때때로 X.500-lite라고 불리기도 합니다.

클라이언트는 Directory System Agent (DSA)라고 불리는 LDAP서버에 접속해서 LDAP세션을 시작합니다. DSA서버는 기본적으로 TCP와 UDP를 사용하고, 포트는 389번이나 LDAPS (SSL기능이 들어간 LDAP)은 636번을 사용합니다. 한번 세션이 연결된 클라이언트는 별도의 인증없이 지속적으로 서버에서 필요한 자료를 요청할수 있습니다. 클라이언트는 동시에 여러개의 요청을 서버에 보낼수 있고, 서버는 요청순서와는 상관없이 처리가 되는대로 결과를 반환합니다. 모든 정보는 Basic Encoding Rules (BER)을 기반으로 정보교환이 됩니다.

아래는 클라이언트가 서버에 요청할수 있는 리스트입니다.

  • StartTLS – use the LDAPv3 Transport Layer Security (TLS) extension for a secure connection
  • Bind – authenticate and specify LDAP protocol version
  • Search – search for and/or retrieve directory entries
  • Compare – test if a named entry contains a given attribute value
  • Add a new entry
  • Delete an entry
  • Modify an entry
  • Modify Distinguished Name (DN) – move or rename an entry
  • Abandon – abort a previous request
  • Extended Operation – generic operation used to define other operations
  • Unbind – close the connection (not the inverse of Bind)

Source:

RPC vs REST vs GraphQL

오랫동안 API개발자들은 RESTful API가 최고라고 생각하고 모든 표준을 RESTful 에 맞춰서 개발을 했어요. 그런데 최근에 RPC나 GraphQL과 같은 다양한 프로토콜에 관심이 옮겨지면서 이제 더이상 RESTful만 고집하던 API세상은 갔어요.

RPC API도 아래와 같이 RESTful API와 비슷한 형태로 API결과를 반환하는게 가능합니다.

GET /listConversations
GET /listMessages?id=123

그리고 JSON형식의 body데이타를 넘겨주는것도 가능합니다.

POST /sendMessages?id=2
{
    "body": "value"
}

물론 http가 아닌 RPC프로토콜을 이용해서 통신을 할뿐이죠. 많은 큰 규모의 테크회사들이 RPC를 이용하는 이유는 PRC통신이 굉장히 쉽고 high performance를 제공하기 때문이에요. 특히 내부적으로 복잡한 마이크로 서비스를 가진 회사들은 마이크로 서비스간에 수억, 수조의 통신이 발생하기 때문에 이걸 전부 http를 거쳐서 RESTful API로 통신하는것보다 군더더기 없는 RPC의 메세지가 훨씬 작아 더 경제적이고 성능면에서도 좋기때문에 최근들어 대규모시스템을 가진 회사들이 특히 RPC를 선호하는 경향이 있습니다.

하지만 RPC라고 전부 좋은것만은 아니에요. 일단 어떤 서비스에서 제공하는 함수를 가지고 외부서비스가 API를 만들기때문에 시스템간에 연결관계가 너무 돈독해집니다. 그러면 독립적으로 움질일때보다 변경이나 삭제등이 필요할때 신속하게 움직일수 없겠죠. 그리고 함수명이 그대로 드러나는 형태라서 각 마이크로서비스의 내부 시스템 디자인과 구현방식이 그대로 노출된다는 단점이 있습니다.

그리고, RPC API는 함수만 일차원적으로 나열된 형태이기 때문에 해당서비스를 이미 잘 알고 있지 않은 경우에 어디서 부터 시작해야할지 막막할수가 있어요. 그리고 그 함수들을 만들기가 너무 쉽기때문에 함수가 매우 많아질 가능성이 크고, 그렇게 되면 이름만으로 함수를 관리하기가 힘들어져서 함수가 중복될수도 있고, 새로 조인한 개발자는 엄청난 양의 함수를 이해하기 위해 많은 노력을 들여야 하는 경우도 생깁니다.

그 반면 RESTful는 최대한 각 서비스들이 독립적으로 운영되도록 디자인하기에 좋은 프로토콜입니다. 표준을 세우고, 그룹을 나누고 룰에 따라서 개발을 한다면 독립성을 유지할수 있는 좋은 프로토콜이지요. 하지만 개발자들은 종종 유혹에 빠집니다. RESTful API에 함수개념의 endpoint를 추가함으로써 RESTful도 RPC도 아닌 그 중간 어딘가의 기준하는 Restful..ish API가 결과적으로 나오는거죠.

RESTful API를 만드는 가장 이상적인 방법은 바로 Hypertext As The Engine Of Application State (HATEOAS)를 구현하는 것입니다. 이것은 클라이언트와 서버를 분리시키는데 목적을 둡니다. 서버와 클라이언트간에 소통되는 모든 디테일이 한눈에 보여야합니다. 별도의 설명서 없이 API만으로도 모든 기능이 이해가 되고 사용이 가능해야하는거죠. 예를 들면 endpoint를 모르면 그냥 /루트 path만 쳐도 거기서 부터 시작해서 어디로 가면 되는지자체가 API를 통해 가이드가 되는거죠. 이걸 이렇게 잘 관리한다는거는 정말 어려운 일이에요. 아주 잘 만들어진 API도 이걸 전부 지키기는 정말 힘들기때문에 잘 못합니다. 하지만 할수만 있다면 정말 완벽한 API를 만드는데 아주 큰 일조를 하게 될 것입니다.

GraphQL은 RESTful과 RPC의 장점을 조합해서 쿼리를 통해 정확하게 내가 필요한 정보만 요청해서 받을수 있는 API타입입니다. 아래는 GraphQL의 Schema 정의의 예제입니다.

type Query {
    listConversations: [Conversation]
}
type Mutation {
    sendMessage(text: String): Message
}
type Conversation {
    id: Int
    title: String
    messages: [Message]
}
type Message {
    id: ID
    text: String
    author: User
}
type User {
    id: ID
    name: String
}

GraphQL을 구현하기 위해서는 API에서 반환하는 모든 데이타를 위와 같이 타입으로 만들어 놔야합니다. 그러면 GraphQL클라이언트는 정의된 데이타 타입 중 필요한 타입만 아래와 같이 쿼리를 할수가 있어요.

{
  listConversations {
    titie,
    messages {
      text
    }
  }
}

그러면 서버는 요청한 칼럼만 결과로 반환하게 됩니다.

{
  "data": {
    "listConversations": [
      {
        "title": "vim or emacs?",
        "messages": [
          {
            "text": "Real programmers use Notepad."
          }
        ]
      }
    ]
  }
}

GraphQL방식을 이용하면 RESTful이 사용하는 프로토콜을 이용하지만 마치 RPC에서 제공하는 함수를 쓰는것처럼 필요한 함수를 호출하고, 필요한 칼럼만 선택적으로 받기때문에 불필요한 데이타를 전송해야하는 네트워크 트래픽을 절약할수 있어요. 페이스북은 접속과 동시에 엄청나게 큰 쿼리를 단 한번 호출합니다. 그 안에 필요한 모든 데이타가 다 들어있어서 추가적인 요청을 안해도 되기때문에 사용자가 인터넷이 지속적으로 제공되지 않는 장소에 있을때 유용합니다.

아래의 표는 각 API방식이 주는 장단점을 나열한 표입니다. 개발하시는데 도움이 되시길 바랍니다.

Source: Nate Barbettini – API Throwdown: RPC vs REST vs GraphQL, Iterate 2018

Remote Procedure Call (RPC)

안녕하세요. 이번시간에는 Remote Procedure Call, RPC에 대해서 공부해볼게요. RPC는요 말그대로 원격에 있는 프로시져를 호출하기위해 만들어진 프로토콜이에요. TCP상에서 통신하는 프로토콜이구요, 분산시스템을 구현하기 위해 개발되었습니다. RPC는 Client-Server model을 사용하고 있는데요. 당연하게 함수를 제공하는 쪽이 서버가 되는거고, 요청하는 쪽이 클라이언트가 되겠죠.

이렇게 해놓으면 뭐가 좋을까요? 일단 필요한 함수를 내가 다 만들어야될 필요가 없겠죠, 각 서비스들이 하나의 공통 함수를 서비스할 RPC서버를 하나 띄워놓고 공용으로 사용하는 프로시져들을 한곳에서 관리할수있어요. 또 다른경우에는 예를 들어 어떤 연산을 처리하는데 수퍼컴퓨터가 필요하다고 치자구요. 그거 현재 돌아가는 서버에서 돌리면 서버 뻗어버리자나요. 그러니까 그런 복잡한 연산은 그 연산을 돌릴수 있는 장비에 띄워놓고 필요할때마다 다른 서비스들이 요청해서 결과를 받아가도록 할수도 있겠죠. 또 이런 경우도 있을거에요. 회사 내부적으로 마이크로 서비스를 구현한 경우에, 각 서비스들이 어떤 특정 data에 대한 ownership을 가지고 있어서, DB에 아무나 막 접속하게 하는것보다 각 서비스들이 제공하는 RPC를 통해서 다른 내부서비스들이 각자 관리하는 데이타를 필요한 만큼만 RPC로 공개하고 다른 서비스들은 데이타의 형식에 구애받지 않고 RPC로만 서로의 데이타를 공유하게 하는거에요.

일단 RPC프로시져를 만들면 해당 프로시져를 서비스할수 있게 만들어야하는데요, 그걸 가능하게 하기위해서 portmapper라는 프로그램을 사용합니다. 어떤 함수를 만들어놓고, 그함수를 특정 포트에 mapping을 해놓으면, 사용자는 portmapper에 접속해서 사용하고자하는 함수가 몇번포트에 열려있는지를 알아낸뒤, 그 포트로 요청해서 연산결과를 받아냅니다. 그리고 rpcinfo라는 명령어를 통해서 어떤 포트가 어느 프로그램에 연동이 되어있는지를 확인할수 있어요.

$ rpcinfo -p localhost
program vers proto   port
100000     2   tcp   111  portmapper
100000     2   udp   111  portmapper
 22855     1   udp   35621 
 22855     1   tcp   56094

위의 결과를 보시면, 현재 portmapper가 111포트에 떠있고, 그 밑으로 22855라는 프로그램이 UDP는 35621포트에, TCP요청은 56094에 mapping이 되어있는걸 확인하실수 있으실거에요. 그런데 22855라는 프로그램이 어떤건지 숫자만봐서는 알기가 힘들잖아요. 그래서 rpcinfo명령어를 쳤을때 해당 서비스가 어떤 서비스인지 힌트를 보여주고 싶다 할때는 /etc/rcp라는 파일을 열어서 그 안에 해당 서비스의 이름과 서비스넘버를 등록하시면 다시 rpcinfo명령어를 실행했을때, 맨 끝에 어떤 프로그램인지 보여줍니다.

$ cat /etc/rpc
...
avg 22855
$ rpcinfo -p localhost
program vers proto   port
100000     2   tcp   111  portmapper
100000     2   udp   111  portmapper
 22855     1   udp   35621  avg
 22855     1   tcp   56094  avg

Source:

DataDog 로그검색

이번 시간에는 DataDog의 Log를 검색하는 방법에 대해서 이야기 해볼게요.

DataDog 로그

DataDog의 로그를 클릭해서 보시면 아래와 같이 상세팝업이 뜨는데요 크게는 태그검색과 메세지 검색으로 나뉩니다. 태그는 Key-value쌍으로 검색을 할수 있고, Message는 아래 화면의 회색상자에 들어있는 부분으로 쿼리검색에 주로 이용합니다.

태그검색

로그를 클릭해보시면 Tags와 중간에 Message그리고 Event Attribute들이 상세하게 보이실거에요. Tag나 Event Attribute들은 값이나 키를 클릭하면 아래와 같이 메뉴가 뜨고, 해당 키의 해당 값을 검색할지, 배제할지를 선택할수 있어요.


팝업에서 Search for @status:200을 클릭하면 아래와 같이 검색창에 해당 태그로 필터링하도록 검색태그가 들어갑니다.

메세지 검색

검색쿼리에 어떤 key를 명시하지 않고 그냥 문자열만 넣는다면 그건 메세지에서 문자열 검색을 하는건데요. 아래와 같이 그냥 쌍따옴표에 검색할 문자열을 넣어서 검색을 하는데 주로 정규식과 같이 복잡한 연산이 필요한 검색에 이용됩니다.

참고로, 메세지 내에서 특정 문자를 제외한 나머지 로그를 보시고 싶은경우에는 앞에 -를 붙여서 -"*/user/show*"로 검색하시면 해당 문자열이 포함되지 않은 로그만 보여줍니다.

source: https://docs.datadoghq.com/logs/search_syntax/

Redis의 CONFIG SET명령어

CONFIG SET명령어는 Redis서버가 돌아가고 있는 상태에서 서버를 재시작하지 않고 설정값을 변경하기 위해 사용되는 명령어 입니다.

설정값을 세팅하기 전에 어떤 설정값들이 존재하는지를 CONFIG GET명령어를 통해서 조회를 합니다.

CONFIG SET을 통해서 설정된 값들은 즉시 Redis에 의해 적용되며 다른 값으로 다시 설정할때까지 계속 Redis서버에 남아있게됩니다. 모든 값들은 redis.conf에 설정되는 key-value와 동일하며, CONFIG GET에서 말씀드린대로 아래의 두가지만 예외를 가집니다:

  • 숫자나 사이즈를 기재할때 redis.conf에서는 가능했던 10k, 2gb등 줄여쓰기를 지원하지 않습니다. 정수로된 설정값을 저장할때는 64-bit정수값을 그대로 다 쓰셔야합니다.
  • redis.conf에서 save명령어는 여러개의 정수로 설정값을 받지만 CONFIG SET를 통해서 값을 설정할때는 하나의 문자열로 쓰셔야합니다.

위의 목록에서 두번째 save와 관련된 부분에 대해서 좀더 설명을 드리자면요, redis.conf에 아래와 같은 설정이 있다면:

save 900 1
save 300 10

위의 설정은 최소 1번의 변경이 있었다면 dataset을 900초뒤에 저장하고, 10회의 변경이 있었다면 300초뒤에 저장하라는 뜻이에요. 이걸 CONFIG SET을 통해서 설정한다고 하면 CONFIG SET SAVE "900 1 300 10"이렇게 하셔야하는거죠.

아래는 기본값을 가지던 save의 값을 다른 값으로 변경해보는 예제입니다.

127.0.0.1:6379> CONFIG GET save
1) "save"
2) "3600 1 300 100 60 10000"
127.0.0.1:6379> CONFIG SET SAVE "900 1 300 10"
OK
127.0.0.1:6379> CONFIG GET save
1) "save"

source: https://redis.io/commands/config-set

Redis의 CONFIG GET명령어

CONFIG GET 명령어는 현재 돌아가고 있는 Redis서버의 설정값을 읽어오기 위한 명령어입니다. Redis 2.4버젼에서는 모든 설정값을 읽어오도록 지원하지 않지만 2.6버젼에서는 모든 설정값을 읽어올수 있게 업그레이드가 되었답니다.

CONFIG GET명령어는 오직 하나의 인자만 받습니다. 모든 설정값은 key-value 쌍으로 이루어져있고, 아래와 같이 와일드카드를 사용해서 여러개를 한꺼번에 읽어올수도 있습니다.

127.0.0.1:6379> config get *max-*-entries*
1) "hash-max-ziplist-entries"
2) "512"
3) "set-max-intset-entries"
4) "512"
5) "zset-max-ziplist-entries"
6) "128"

어떤 설정값이 있는지 모르시겠다고요? 그렇다면 CONFIG GET *명령어를 통해서 모든 설정값의 key-value 쌍을 가져올수 있어요.

127.0.0.1:6379> CONFIG GET *
  1) "rdbchecksum"
  2) "yes"
...
263) "requirepass"
264) ""

여기에 나열된 모든 설정값은 redis.conf파일에 들어가는 것과 동일합니다. 단 아래의 두가지 예외사항만 제외하고요:

  • 숫자나 사이즈를 기재할때 redis.conf에서는 가능했던 10k, 2gb등 줄여쓰기를 지원하지 않습니다. 정수로된 설정값을 조회해보면 64-bit정수값이 그대로 다나와요.
  • redis.conf에서 save명령어는 여러개의 정수로 설정값을 받지만 CONFIG GET를 통해서 값을 조회해보면 하나의 문자열로 반환을 합니다.

위의 목록에서 두번째 save와 관련된 부분에 대해서 좀더 설명을 드리자면요, redis.conf에 아래와 같은 설정이 있다면:

save 900 1
save 300 10

이 말은, 최소 1번의 변경이 있었다면 900초뒤에 저장하고, 10회의 변경이 있었다면 300초뒤에 저장하라는 뜻이에요. 이걸 CONFIG GET을 통해서 조회하면 “900 1 300 10″과 같은 하나의 문자열이 나옵니다. 아래는 초기값을 변경하지 않았을때 로컬에서 돌려본 값이에요.

127.0.0.1:6379> CONFIG GET save
1) "save"
2) "3600 1 300 100 60 10000"

source: https://redis.io/commands/config-get

Redis Quick Start

본문에서는 Redis쌩초보를 위한 사용법을 설명한 자료입니다. 아래와 같은 내용을 소개하고자합니다.

  • Redis다운받고 설치하기
  • redis-cli로 Redis서버에 접속하기
  • 애플리케이션에서 Redis사용하기
  • Redis의 영구성에 대해 이해하기
  • 추가적인 Redis관련 툴 설치하기
  • 깊이있는 Redis공부를위해 뭘하면 되는지 알기

Redis설치하기

Redis를 설치하는데 가장 추천하는 방법은 다른 군더더기 없이 소스코드를 다운받아서 설치하는 방법이에요. 그러면 GCC컴파일러랑 libc만 있으면 되거든요. 리눅스에서 제공하는 패키지 매니저를 통해서 설치를하면 어째 최신버젼이 다운받아지지가 않더라고요. 그래서 그방법은 비추.

redis.io에 가시면 Redis를 tar로 묶어놓은 파일을 다운 받을수 있으세요. 최신버젼중에 가장 안정된 버젼은 http://download.redis.io/redis-stable.tar.gz 요 링크를 통해서 아래와같이 다운받아서 설치하시면 됩니다.

wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make

이 시점에서 make test를 한번 실행해주면 설치가 잘되었는지 확인할수 있어요. make을 통해서 소스파일들이 컴파일이 되고나면 Redis가 제공하는 다양한 명령어들을 실행할수 있게 되는데요 아래와 같습니다.

  • redis-server Redis 서버
  • redis-sentinel Failover를 모니터링하는 툴
  • redis-cli 서버에 접속해서 정보를 받아올수 있는 Redis클라이언트
  • redis-benchmark Redis의 퍼포먼스를 모니터링할수 있는 툴
  • redis-check-aofredis-check-rdb (3.0 이하버젼에서는 redis-check-dump)는 데이타오류 체크

현재 여러분들은 아마도 Home디렉토리나 Download디렉토리에서 이걸 실행하셨을거에요. 그렇게되면 관리가 힘들어질거 같으니 아래의 명령어를 실행해서 Redis서버랑 클라이언트를 제대로 된 위치로 옮겨볼까요?

sudo cp src/redis-server /usr/local/bin/
sudo cp src/redis-cli /usr/local/bin/

Redis 시작하기

Redis를 실행하는 가장 손쉬운 방법은 바로 redis-server명령어를 실행하는 것입니다.

$ redis-server
83406:C 05 Aug 2020 10:01:17.983 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
83406:C 05 Aug 2020 10:01:17.983 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=83406, just started
83406:C 05 Aug 2020 10:01:17.983 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
83406:M 05 Aug 2020 10:01:17.984 * Increased maximum number of open files to 10032 (it was originally set to 256).
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 6.0.6 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 83406
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

83406:M 05 Aug 2020 10:01:17.985 # Server initialized
83406:M 05 Aug 2020 10:01:17.986 * Ready to accept connections

Redis가 정상작동 확인

외부 프로그램들은 TCP소켓을 이용해서 Redis와 소통합니다. 물론 프로토콜은 Redis가 특별히 정한 프로토콜을 이용하구요. 다양한 언어로 Redis클라이언트를 제공하고 있으니 프로토콜이 몬지는 크게 걱정 안하셔도 되요. 또한, Redis는 서버에 접속하여 command line명령어를 통해 손쉽게 지지고 볶고 할수 있는데 바로 그 명령어 이름이redis-cli라는 애에요.

일단 아래 명령어를 따라해보세요. 참고로 위에 띄워놓은 서버는 그대로 두고 다른 창을 열어서 방금띄운 Redis서버와 통신을 시도하는 겁니다.

$ redis-cli ping
PONG

redis-cli ping이라는 명령어를 날리면, 서버가 PONG하고 대답해요 ㅋㅋ 재밌죠. redis-cli명령어 뒤에 여러 인자를 날리면 얘가 localhost의 6379포트로 통신을 시도하게 됩니다. 서버를 기본포트가 아닌 다른 번호를 설정해서 띄웠거나, 서버가 로컬에 있지 않은 경우에는 redis-cli 명령어를 실행할때 해당 서버의 호스트나 포트번호를 명시해줄수 있어요.

redis-cli를 아무 인자없이 그냥 실행했을때는, 마치 해당 서버에 터미널로 접속한것 처럼 세션을 열고 대화형식으로 Redis명령어만 사용해서 다양한 제어를 할수있어요.

$ redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set mykey somevalue
OK
127.0.0.1:6379> get mykey
"somevalue"

이 상태에서 Redis와 대화를 나눌수 있게 되는데요, 좀더 다양한 Redis 명령어를 연습하고 싶으신분은 Redis가 제공하는 데이타 타입 알아보기를 추천드려요.

source: https://redis.io/topics/quickstart

Redis configuration

이번시간에는 Redis서버의 설정파일을 조작하는 방법에 대해서 알아보도록할게요. Redis서버를 시작할때 굳이 config파일을 사용할 필요는 없어요 자체적으로 default config파일이 있어서 그걸 그냥 쓰거든요. 근데 config파일을 바꿀수는 있긴 한데 그닥 추천하지는 않아요 그냥 테스트나 개발목적으로 해보시는거만 추천드려요.

Redis에 config를 변경하는 가장 정석은 바로 redis.conf라는 설정파일에 설정값을 저장해서 그 파일을 Redis에 넘겨주는건데요. 파일안에 값을 설정하는 형식은 다음과 같아요:

keyword argument1 argument2 ... argumentN

예를 들면 뭐 이런식:

slaveof 127.0.0.1 6380

argument의 구분은 space로 하는데요 문자열에 space를 넣어야하는 경우에는 이렇게 따옴표를 넣어서 이게 하나의 argument이다 라고 명시해줄수 있어요:

requirepass "hello world"

각 config파일의 설정값들은 버젼마다 조금씩 다른데요 자세한건 아래 버젼별 redis.config를 참고해주세요:

Passing arguments via the command line

Redis의 설정값을 변경하는 또다른 방법은 바로 redis-server를 실행할때 command line에 설정값을 넘겨주는 식으로 변경할수 있어요.

./redis-server --port 6380 --slaveof 127.0.0.1 6379

이렇게 넘겨받은 config들은 메모리에 임시로 config파일을 만들어서 저장이 되는데요. 그 파일의 형식은 redis.conf랑 동일해요. 그 말인 즉슨, command line에 설정값을 argument으로 전달하면 그 설정값들을 redis.conf형식으로 convert하고 그걸 메모리에 올려놓고 계속 갖다 쓴다는거죠.

Changing Redis configuration while the server is running

제가 찾고 있던 아주 유용한 팁! redis.conf나 command line으로 설정값을 넘겨주는 방식은 redis를 다시 시작해야한다는 의미자나요. Redis가 실제로 운영되고 있는 상태에서 그건 거의 장사 안하겠다는 의미죠 ㅎㅎ 불필요하게 restart해야한다면 뭐..공지띄우고 어쩌고 저쩌고 해야겠지만…서버가 돌아가는 상태에서 config를 바꿀수 있다면 정말 끝내주지 않아요?

서버를 멈추거나 재시작하지 않고 설정을 바꾸는 마법의 command는 바로 CONFIG SETCONFIG GET이에요. 모든 설정을 CONFIG SET을 통해서 변경할수 있지는 않는데 대부분의 것들은 설정변경이 가능하답니다. 자세한건 링크 누르셔서 읽어보세요.

기존에 redis.conf파일을 이용해서 서버를 실행했는데, CONFIG SET명령어를 이용해서 설정을 변경했다고 해도 redis.conf파일안의 내용이 바뀌는건 아니에요. 메모리에 떠있는 파일만 변경되는것이기 때문에 서버를 다시 실행시키면 임시로 변경된 내용은 저장되지 않았기때문에 기존에 redis.conf만 가지고 실행했을 당시로 돌아갑니다.

그러니까 운영중에 설정을 perfanantly 바꿔야하는 경우에는 redis.conf파일의 설정값도 함께 바꿔주는거 잊지마세요. 참고로 Redis 2.8부터는 CONFIG REWRITE이라는 명령어를 제공하는데 얘를 이용해서 설정을 바꾸는 경우에는 얘가 redis.conf파일을 재빨리 스캔해서 기존에 없는 값들만 바꿀수 있고, 설정값이 없어서 추가를 할수 있는 항목이라도 그 값이 default와 동일하면 파일에 추가되지 않습니다.

Configuring Redis as a cache

Redis는 key를 통해 value를 빠르게 제공하는 NoSQL database입니다. 이걸로많은 부분에 활용을 할수 있지만 Redis에서는 특별히 각 key값에 expire time을 부여함으로써 cache로도 활용할수 있도록 제공하고 있습니다.

maxmemory 2mb
maxmemory-policy allkeys-lru

위의 설정을 보시면 key에 EXPIRE command를 사용할 필요없이 Redis에 할당된 2메가의 메모리가 모두 소진된 경우 LRU 알고리즘에 입각한 순서대로 key가 사라지게 되는거에요. 이 경우에는 Redis가 memcached랑 비슷한 방식으로 캐시를 하게 되는거죠. LRU방식으로 캐시를 하는 방법에 대해서 더 자세히 알아보고 싶으시면 여기를 눌러서 확인해주세요.

Source: https://redis.io/topics/config

sqlalchemy.sql.Select.with_hint()

이 함수는 SQLAlchemy를 사용하여 쿼리를 할때, 추가적으로 index를 어떤걸 사용하라든지 아니면 쿼리에 대한 다른 뭔가 추가정보를 주고 싶을때 힌트를 주는 용도로 사용을 합니다.

query = query.with_hint(Table, "USE INDEX (column)")

위의 쿼리에서는 Table이라는 테이블의 column이라는 필드를 index로 사용하여 해당 쿼리를 실행하라는 의미가 됩니다.

source: https://www.kite.com/python/docs/sqlalchemy.sql.Select.with_hint