SETRANGE
, GETRANGE
SETRANGE key offset value
SETRANGE
명령어는 지정된 오프셋부터 시작하여 키에 저장된 문자열의 일부를 전체 값 길이에 대해 덮어쓴다.GETRANGE key start end
GETRANGE
명령어는 키에 저장된 문자열 값의 부분 문자열을 가져온다.redis> SET key1 "Hello World"
"OK"
redis> SETRANGE key1 6 "Redis"
(integer) 11
redis> GET key1
"Hello Redis"
redis> SETRANGE key2 6 "Redis" # 초기값이 설정되어 있지 않은 오프셋에 대해서는 빈문자열로 간주한다
(integer) 11
redis> GET key2
"Redis"
redis>
redis> SET mykey "This is a string"
"OK"
redis> GETRANGE mykey 0 3
"This"
redis> GETRANGE mykey -3 -1
"ing"
redis> GETRANGE mykey 0 -1
"This is a string"
redis> GETRANGE mykey 10 100
"string"
INCR
, INCRBY
, INCRBYFLOAT
, DECR
, DECRBY
INCR key
INCR
명령어는 키에 저장된 숫자를 1씩 증가시킨다. 키가 존재하지 않으면 연산을 수행하기 전에 0으로 설정된다. 키가 잘못된 유형의 값을 포함하거나 정수로 표현할 수 없는 문자열 값을 포함하고 있으면 오류가 발생한다.INCRBY key increment
INCRBY
명령은 키에 저장된 숫자를 지정된 increment만큼 증가시킨다.INCRBYFLOAT key increment
INCRBYFLOAT
명령어는 키에 저장된 부동 소수점 숫자를 지정된 increment만큼 증가시킨다.DECR key
DECR
명령어는 키에 저장된 숫자를 1 감소시킨다.DECRBY key decrement
DECRBY
명령어는 키에 저장된 숫자를 감소분만큼 감소시킨다.redis> SET mykey "10"
"OK"
redis> INCR mykey
(integer) 11
redis> GET mykey
"11"
redis> SET mykey "10"
"OK"
redis> INCRBY mykey 5
(integer) 15
redis> SET mykey 10.50
"OK"
redis> INCRBYFLOAT mykey 0.1
"10.6"
redis> INCRBYFLOAT mykey -5
"5.6"
redis> SET mykey 5.0e3
"OK"
redis> INCRBYFLOAT mykey 2.0e2
"5200"
redis> SET mykey "10"
"OK"
redis> DECR mykey
(integer) 9
redis> SET mykey "234293482390480948029348230948"
"OK"
redis> DECR mykey
(error) value is not an integer or out of range
redis> SET mykey "10"
"OK"
redis> DECRBY mykey 3
(integer) 7
INCR
및 EXPIRE
를 함께 사용하여 지정된 시간 내에 구분된 최근 N개의 페이지 뷰만 세는 카운터를 생성할 수 있다.GETSET
을 사용할 수 있다.DECR
또는 INCRBY
와 같은 다른 원자적 증가/감소 명령을 사용할 수 있다. 예를 들어, 온라인 게임에서 여러 사용자의 점수를 생각해볼 수 있다.레이트 리미터는 특정 시간 동안 요청의 수를 제한하는 데 사용된다. 이를 통해 서버를 과도하게 사용하는 경우를 방지하고 서비스의 안정성을 유지할 수 있다.
INCR
을 사용하여 두 가지 방법으로 구현할 수 있다. 예를 들어 IP 주소당 초당 최대 10개의 요청으로 API 호출 수를 제한하는 것으로 가정한다.
INCR
명령을 호출하여 요청을 카운트한다.import (
"context"
"errors"
"time"
"github.com/go-redis/redis/v9"
)
func LimitAPICall(ip string, client *redis.Client) error {
ts := time.Now().Unix()
keyname := ip + ":" + string(ts)
// Redis의 TxPipeline을 사용하여 트랜잭션 시작
pipe := client.TxPipeline()
// INCR keyname 및 만료를 10초로 설정
incrResult := pipe.Incr(context.Background(), keyname)
pipe.Expire(context.Background(), keyname, 10*time.Second)
// 트랜잭션 실행
if _, err := pipe.Exec(context.Background()); err != nil {
return err
}
// INCR 작업 결과 가져오기
current, err := incrResult.Result()
if err != nil {
return err
}
// 요청 수가 제한을 초과하는지 확인
if current > 10 {
return errors.New("too many requests per second")
}
// 제한이 초과되지 않으면 API 호출 수행
PerformAPICall()
return nil
}
import (
"context"
"errors"
"github.com/go-redis/redis/v9"
)
func LimitAPICall(ip string, client *redis.Client) error {
// 현재 IP 주소의 요청 수 조회
current := client.LLen(context.Background(), ip).Val()
// 요청 수가 10 초과하는지 확인
if current > 10 {
return errors.New("too many requests per second")
}
// 키가 존재하지 않는 경우 IP 주소를 리스트에 추가하고 1초 후 만료
if client.Exists(context.Background(), ip).Val() == 0 {
_, err := client.TxPipelined(context.Background(), func(pipe redis.Pipeliner) error {
pipe.RPush(context.Background(), ip, ip)
pipe.Expire(context.Background(), ip, 1)
return nil
})
if err != nil {
return err
}
} else {
// 키가 이미 존재하는 경우 IP 주소를 리스트에 추가
client.RPushX(context.Background(), ip, ip)
}
// API 호출 수행
PERFORM_API_CALL()
return nil
}
Redis의 SETRANGE 및 GETRANGE는 문자열 조작에 유용하며, INCR 및 DECR은 카운팅 및 증감 작업시 유용하다. 이러한 기능들은 데이터 조작의 효율성을 높이고, 원자성을 보장하여 안정적인 애플리케이션을 구축하는 데 기여한다.