redis 사무동력 노드 자바 대학 정리

7161 단어 redis사무.
우 리 는 redis 가 추구 하 는 것 이 간단 하고 빠 르 며 효율 적 이라는 것 을 알 고 있 습 니 다.이런 상황 에서 window 플랫폼 을 지원 하 는 것 을 거절 하고 sqlserver 를 배 울 때 우 리 는 업무 가 비교적 복잡 한 것 이라는 것 을 알 고 있 습 니 다.그래서 redis 로 옮 기 면 당연히 redis 는 그렇게 간단 하고 순수한 것 이 아 닙 니 다.그러나 사 무 는 우리 가 프로그램 을 써 서 피 할 수 없 는 장면 입 니 다.그래서 redis 작 가 는 간단 한 사무 체 제 를 절충 적 으로 썼 다.
하나: 실무,일,총무
구체 적 으로 사무 가 무엇 인지,무엇 을 보증 해 야 하 는 지...이 건 말 할 필요 가 없 을 것 같 습 니 다.먼저 무작정 redis 매 뉴 얼 을 보고 마력 을 음미 하 세 요.

1. multi,exec
sqlserver 어떻게 했 는 지 기억 나 세 요?보통 이런 세 가지 절차 입 니 다.사 무 를 만 들 고 명령 을 내 리 며 사 무 를 수행 합 니 다.그 렇 죠?redis 에 대응 하 는 것 은 요?multi 는 트 랜 잭 션 을 만 들 고 redis 명령 을 입력 하 며 마지막 으로 exec 로 명령 을 수행 합 니 다.아래 와 같이:

이 를 통 해 알 수 있 듯 이 제 가 set 명령 을 마 친 후에 피드백 정 보 는 QUEUED 입 니 다.마지막 에 제 가 exec 를 실행 해 야 이 명령 들 이 진정 으로 실 행 될 수 있 습 니 다.바로 이렇게 간단 합 니 다.모든 것 이 그렇게 순 조 롭 고 조금도 질질 끌 지 않 습 니 다.어떤 사람들 은 사실 업무 중 에 rollback 작업 이 있 지만 redis 에서 보지 못 한 것 같 습 니 다.안 타 깝 게 도 redis 에 rollback 작업 이 없습니다.예 를 들 어 아래 와 같 습 니 다.

그림 에서 나 는 고의로 lpush 명령 으로 string 을 실행 했다.당연히 성공 하지 못 할 것 이 라 고 짐작 할 수 있 지만 결과 에서 당신 은 무엇 을 보 았 습 니까?두 개 OK,한 개 Error,이것 이 바로 업무 의 원자 성 을 위반 한 것 입 니 다.그런데 제 가 어떻게 반박 해 야 합 니까? reids 는 데이터 구조 서버 일 뿐 입 니 다.얼마나 간단 한 일 인지 만 걸음 물 러 나 면 분명 한 오류 명령 이 바로 돌아 올 것 입 니 다.예 를 들 어 제 가 일부러 lpush 를 lpush 1 로 썼 습 니 다.

2. watch
멀 티 뒤에 있 는 세 개의 set 명령 을 보고 나 서 뭔 가 허전 한 느낌 이 들 었 는 지 모 르 겠 습 니 다.뭐라고 해 야 할 까요?명령 이 정확 하 다 면 redis 는 함께 임 무 를 수행 할 것 을 보증 합 니 다.명령 은 함께 수행 된다 고 하지만 누가 제 가 명령 을 수행 하 는 과정 에서 다른 client 가 이 값 을 수정 하지 않 을 것 이 라 고 보증 할 수 있 습 니까?만약 이 값 들 을 수정 했다 면,나의 exec 는 또 어떤 의미 가 있 습 니까?괜찮아,이런 나 쁜 거리의 수요,redis 가 어떻게 수수방관 할 수 있 겠 어??이곳 의 watch 가 당신 을 도 울 수 있 습 니 다.

WATCH
WATCH key [key ...]
하나 이상 감시 하기 key ,만약 업무 수행 전에 이것(또는 이것들) key 다른 명령 에 의 해 변경 되면 사 무 는 중 단 될 것 이다.
위 는 바로 redis 매 뉴 얼 에서 watch 에 대한 설명 입 니 다.사용 하기 가 간단 한 것 같 습 니 다.바로 제 가 multi 전에 watch 로 제 가 수정 하고 자 하 는 key 를 감시 하 는 것 입 니 다.만약 에 제 가 exec 전에 multi 이후 의 이 시간 에 key 가 다른 client 에 의 해 수정 되면 exec 는 실 패 를 하고 돌아 갑 니 다.이렇게 간단 합 니 다.제 가 예 를 들 겠 습 니 다.
 
2.원리 탐구
트 랜 잭 션 작업 에 관 한 소스 코드 는 대부분 redis 소스 코드 에 있 는 multi.c 입 니 다. 파일 에서 다음 에 나 는 하나씩 간단하게 분석 할 것 이다.
1. multi
redis 의 소스 코드 에 서 는 대략 이렇게 쓰 여 있 습 니 다.

void multiCommand(redisClient *c) {
   if (c->flags & REDIS_MULTI) {
     addReplyError(c,"MULTI calls can not be nested");
     return;
   }
   c->flags |= REDIS_MULTI;
   addReply(c,shared.ok);
이 코드 에서 멀 티 는 리 디 스 클 라 이언 트 의 REDIS 만 간단하게 볼 수 있 습 니 다.MULTI 상태 가 열 리 면 이 redis 클 라 이언 트 가 트 랜 잭 션 모드 에 들 어 갔다 는 것 을 알려 줍 니 다.
2. 생 성 명령
redisClient 에 multiState 명령 이 있 습 니 다:

typedef struct redisClient {

  。。。

  multiState mstate;   /* MULTI/EXEC state */

  。。。

} redisClient;
주석 에서 도 이 명령 이 multi/exec 와 관련 이 있 는 것 을 보 았 을 것 입 니 다.다음 에 궁금 한 것 은 multiState 의 정 의 를 보 겠 습 니 다.

typedef struct multiState {

  multiCmd *commands;   /* Array of MULTI commands */

  int count;       /* Total number of MULTI commands */

  int minreplicas;    /* MINREPLICAS for synchronous replication */

  time_t minreplicas_timeout; /* MINREPLICAS timeout as unixtime. */

} multiState;
multiState 라 는 매 거 진 에서 아래 에*command 명령 이 있 는 것 을 볼 수 있 습 니 다.주석 에서 그것 이 가리 키 는 것 은 하나의 배열 입 니 다.그것 이 바로 당신 의 몇 가지 명령 입 니 다.다음은 실제 commands 의 총 수 를 볼 수 있 는 count 가 있 습 니 다. 
3. watch
뒤의 exec 를 편리 하 게 말 하기 위해 watch 가 어떻게 이 루어 졌 는 지 말씀 드 리 고 싶 습 니 다.multi.c 소스 코드 에 이렇게 쓰 여 있 습 니 다.

typedef struct watchedKey {
   robj *key;
   redisDb *db;
 } watchedKey;
 
 void watchCommand(redisClient *c) {
   int j;
 
   if (c->flags & REDIS_MULTI) {
     addReplyError(c,"WATCH inside MULTI is not allowed");
     return;
   }
   for (j = 1; j < c->argc; j++)
     watchForKey(c,c->argv[j]);
   addReply(c,shared.ok);
 }
 
 /* Watch for the specified key */
 void watchForKey(redisClient *c, robj *key) {
   list *clients = NULL;
   listIter li;
   listNode *ln;
   watchedKey *wk;
 
   /* Check if we are already watching for this key */
   listRewind(c->watched_keys,&li);
   while((ln = listNext(&li))) {
     wk = listNodeValue(ln);
     if (wk->db == c->db && equalStringObjects(key,wk->key))
       return; /* Key already watched */
   }
   /* This key is not already watched in this DB. Let's add it */
   clients = dictFetchValue(c->db->watched_keys,key);
   if (!clients) {
     clients = listCreate();
     dictAdd(c->db->watched_keys,key,clients);
     incrRefCount(key);
   }
   listAddNodeTail(clients,c);
   /* Add the new key to the list of keys watched by this client */
   wk = zmalloc(sizeof(*wk));
   wk->key = key;
   wk->db = c->db;
   incrRefCount(key);
   listAddNodeTail(c->watched_keys,wk);
 }
이 코드 에서 가장 핵심 적 인 것 은:

  /* This key is not already watched in this DB. Let's add it */

  clients = dictFetchValue(c->db->watched_keys,key);
바로 dicFetchValue 라 는 사전 방법 을 통 해 watchedkeys 에서 지정 한 key 의 value 를 찾 았 습 니 다.이 value 는 clients 의 링크 입 니 다.이 key 에 관 한 모든 client 를 찾 고 싶 은 것 임 을 설명 합 니 다.마지막 으로 이번 key 를 redisclient 의 watched 에 넣 을 것 입 니 다.keys 사전 에서 다음 코드:

  /* Add the new key to the list of keys watched by this client */

  wk = zmalloc(sizeof(*wk));

  wk->key = key;

  wk->db = c->db;

  incrRefCount(key);

  listAddNodeTail(c->watched_keys,wk);
굳이 그림 을 그 려 야 한다 면 아마 그 럴 것 이다.

그 중 watchedkey 는 사전 구조 입 니 다.사전 의 키 는 위의 key 1,key 2 입 니 다.value 는 client 의 링크 입 니 다.그러면 어떤 key 에서 어떤 client 에 의 해 감시 되 고 있 는 지 잘 알 고 있 습 니 다.
4.exec
이 명령 에는 대략 두 가지 일 을 했다.
<1>:   판단 c->flags=REDISDIRTY_EXEC 열 었 는 지 여부 입 니 다.그렇다면 트 랜 잭 션 discardTransaction(c)을 취소 합 니 다.즉,이 키 는 다른 client 에 의 해 수정 되 었 습 니 다.
<2>:   수정 되 지 않 았 다 면 for 는 다음 그림 의 두 가지 정보 와 같이 comannd[]의 명령 을 반복 적 으로 실행 합 니 다.
  
자,대충 그렇게 말씀 드 리 겠 습 니 다.도움 이 되 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기