관리 메뉴

nalaolla

Redis – SpringBoot2 redis cluster : strings, lists, hashs, sets, sortedsets, geo, hyperloglog 본문

SPRING/Redis

Redis – SpringBoot2 redis cluster : strings, lists, hashs, sets, sortedsets, geo, hyperloglog

날아올라↗↗ 2020. 2. 18. 14:07
728x90

SpringBoot2와 redis cluster를 연동하고, redis command에 대해 설명합니다. 다음을 참고하여 프로젝트를 하나 생성합니다.
>> Intellij Community 프로젝트생성

Boot를 실행하기 위한 Application Class 생성

package com.redis.cluster;

 

@SpringBootApplication

public class RedisClusterApplication {

    public static void main(String[] args) {

        SpringApplication.run(RedisClusterApplication.class, args);

    }

}

build.gradle 수정

spring-boot-starter-data-redis를 이용하여 redis cluster를 연동합니다.

plugins {

    id 'org.springframework.boot' version '2.1.4.RELEASE'

    id 'java'

}

 

apply plugin: 'io.spring.dependency-management'

 

group = 'com.rest'

version = '0.0.1-SNAPSHOT'

sourceCompatibility = '1.8'

 

configurations {

    compileOnly {

        extendsFrom annotationProcessor

    }

}

 

repositories {

    mavenCentral()

}

 

dependencies {

    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

    implementation 'org.springframework.boot:spring-boot-starter-freemarker'

    implementation 'org.springframework.boot:spring-boot-starter-web'

    implementation 'org.springframework.boot:spring-boot-starter-data-redis'

    implementation 'com.google.code.gson:gson'

    compileOnly 'org.projectlombok:lombok'

    runtimeOnly 'com.h2database:h2'

    runtimeOnly 'mysql:mysql-connector-java'

    annotationProcessor 'org.projectlombok:lombok'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'

}

application.yml 수정

h2, jpa, redis 설정을 추가합니다. cluster 노드 정보를 넣고, redis에 패스워드가 있으면 패스워드 정보도 추가합니다.

server:

  port: 8081

 

spring:

  datasource:

    url: jdbc:h2:tcp://localhost/~/test

    driver-class-name: org.h2.Driver

    username: sa

  jpa:

    database-platform: org.hibernate.dialect.H2Dialect

    properties.hibernate.hbm2ddl.auto: update

    showSql: true

  redis:

    cluster:

      nodes:

        - 15.164.98.87:6300

        - 15.164.98.87:6301

        - 15.164.98.87:6302

        - 15.164.98.87:6400

        - 15.164.98.87:6401

        - 15.164.98.87:6402

    password: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

test/resources 아래에 logback_test.xml 생성

유닛 테스트에서 log를 사용하기 위해 test/resources 아래에 logback_test.xml를 생성합니다.

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE configuration>

 

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

            <pattern>

                %-5level %d{HH:mm:ss} %logger{15}.%method:%line - %msg%n

            </pattern>

        </encoder>

    </appender>

 

    <logger name="com.redis.cluster" level="debug" additivity="false">

        <appender-ref ref="STDOUT" />

    </logger>

</configuration>

RedisClusterTest 생성

Redis가 제공하는 명령어를 실습합니다.

자주 사용하는 기본 명령어

@Test

public void commonCommand() {

    ValueOperations<String, String> valueOps = redisTemplate.opsForValue();

    valueOps.set("key1", "key1value");

    valueOps.set("key2", "key2value");

    // Key 타입 조회.

    assertEquals(DataType.STRING, redisTemplate.type("key1"));

    // 존재하는 Key의 개수를 반환.

    assertSame(2L, redisTemplate.countExistingKeys(Arrays.asList("key1", "key2", "key3")));

    // Key가 존재하는지 확인

    assertTrue(redisTemplate.hasKey("key1"));

    // Key 만료 날짜 세팅

    assertTrue(redisTemplate.expireAt("key1", Date.from(LocalDateTime.now().plusDays(1L).atZone(ZoneId.systemDefault()).toInstant())));

    // Key 만료 시간 세팅

    assertTrue(redisTemplate.expire("key1", 60, TimeUnit.SECONDS));

    // Key 만료 시간 조회

    assertThat(redisTemplate.getExpire("key1"), greaterThan(0L));

    // Key 만료 시간 해제

    assertTrue(redisTemplate.persist("key1"));

    // Key 만료시간이 세팅 안되어있는경우 -1 반환

    assertSame(-1L, redisTemplate.getExpire("key1"));

    // Key 삭제

    assertTrue(redisTemplate.delete("key1"));

    // Key 일괄 삭제

    assertThat(redisTemplate.delete(Arrays.asList("key1", "key2", "key3")), greaterThan(0L));

}

String structure command

redis command set, get에 대한 내용입니다.

@Test

public void opsValue() {

    ValueOperations<String, String> valueOps = redisTemplate.opsForValue();

    Collection<String> cacheKeys = new ArrayList<>();

    String cacheKey = "value_";

    for (int i = 0; i < 10; i++) {

        cacheKeys.add(cacheKey + i);

        valueOps.set(cacheKey + i, String.valueOf(i), 60, TimeUnit.SECONDS);

    }

    List<String> values = valueOps.multiGet(cacheKeys);

    assertNotNull(values);

    assertEquals(10, values.size());

    log.info("##### opsValue #####");

    log.info("{}", values);

}

##### opsSortedSet #####

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Lists structure command – 순서 있음. value 중복 허용

redis command lpush, llen, lrange, lpop, rpop에 대한 내용입니다.

@Test

public void opsList() {

    ListOperations<String, String> listOps = redisTemplate.opsForList();

    String cacheKey = "valueList";

    for (int i = 0; i < 10; i++)

        listOps.leftPush(cacheKey, String.valueOf(i));

 

    assertSame(DataType.LIST, redisTemplate.type(cacheKey));

    assertSame(10L, listOps.size(cacheKey));

    log.info("##### opsList #####");

    log.info("{}", listOps.range(cacheKey, 0, 10));

    assertEquals("0", listOps.rightPop(cacheKey));

    assertEquals("9", listOps.leftPop(cacheKey));

    assertEquals(true, redisTemplate.delete(cacheKey));

}

##### opsList #####

[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Hashes structure command – 순서 없음. key 중복 허용안함, value 중복 허용

redis command hset, hget, hlen, hdel에 대한 내용입니다.

@Test

public void opsHash() {

    HashOperations<String, String, String> hashOps = redisTemplate.opsForHash();

    String cacheKey = "valueHash";

    for (int i = 0; i < 10; i++)

        hashOps.put(cacheKey, "key_" + i, "value_" + i);

 

    assertSame(DataType.HASH, redisTemplate.type(cacheKey));

    assertSame(10L, hashOps.size(cacheKey));

    log.info("##### opsHash #####");

    Set<String> hkeys = hashOps.keys(cacheKey);

    for (String hkey : hkeys) {

       log.info("{} / {}", hkey, hashOps.get(cacheKey, hkey));

    }

    assertEquals("value_5", hashOps.get(cacheKey, "key_5"));

    assertSame(1L, hashOps.delete(cacheKey, "key_5"));

    assertSame(null, hashOps.get(cacheKey, "key_5"));

}

##### opsHash #####

key_0 / value_0

key_1 / value_1

key_2 / value_2

key_3 / value_3

key_4 / value_4

key_6 / value_6

key_7 / value_7

key_8 / value_8

key_9 / value_9

key_5 / value_5

Set structure command – 순서 없음, value 중복 허용안함

redis command sadd, scard, smembers, sismember에 대한 내용입니다.

@Test

public void opsSet() {

    SetOperations<String, String> setOps = redisTemplate.opsForSet();

    String cacheKey = "valueSet";

    for (int i = 0; i < 10; i++)

        setOps.add(cacheKey, String.valueOf(i));

 

    assertSame(DataType.SET, redisTemplate.type(cacheKey));

    assertSame(10L, setOps.size(cacheKey));

    log.info("##### opsList #####");

    log.info("{}", setOps.members(cacheKey));

    assertEquals(true, setOps.isMember(cacheKey, "5"));

}

##### opsSet #####

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

SortedSet structure command – 순서 있음, value 중복 허용안함

rediscommand zadd, zcard, zrange, zrank에 대한 내용입니다.

@Test

    public void opsSortedSet() {

        ZSetOperations<String, String> zsetOps = redisTemplate.opsForZSet();

        String cacheKey = "valueZSet";

        for (int i = 0; i < 10; i++)

            zsetOps.add(cacheKey, String.valueOf(i), i);

 

        assertSame(DataType.ZSET, redisTemplate.type(cacheKey));

        assertSame(10L, zsetOps.size(cacheKey));

        log.info("##### opsSortedSet #####");

        log.info("{}", zsetOps.range(cacheKey, 0, 10));

        assertSame(0L, zsetOps.reverseRank(cacheKey, "9"));

    }

##### opsSortedSet #####

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Geo structure command – 좌표 정보 처리, 타입은 zset으로 저장.

redis command geoadd, geodist, geopos에 대한 내용입니다.

@Test

public void opsGeo() {

    GeoOperations<String, String> geoOps = redisTemplate.opsForGeo();

    String[] cities = {"서울", "부산"};

    String[][] gu = {{"강남구", "서초구", "관악구", "동작구", "마포구"}, {"사하구", "해운대구", "영도구", "동래구", "수영구"}};

    Point[][] pointGu = {{new Point(10, -10), new Point(11, -20), new Point(13, 10), new Point(14, 30), new Point(15, 40)}, {new Point(-100, 10), new Point(-110, 20), new Point(-130, 80), new Point(-140, 60), new Point(-150, 30)}};

    String cacheKey = "valueGeo";

 

    // previous key delete

    redisTemplate.delete(cacheKey);

 

    for (int x = 0; x < cities.length; x++) {

        for (int y = 0; y < 5; y++) {

            geoOps.add(cacheKey, pointGu[x][y], gu[x][y]);

        }

    }

 

    log.info("##### opsGeo #####");

    Distance distance = geoOps.distance(cacheKey, "강남구", "동작구");

    assertNotNull(distance);

    assertEquals(4469610.0767, distance.getValue(), 4);

    log.info("Distance : {}", distance.getValue());

    List<Point> position = geoOps.position(cacheKey, "동작구");

    assertNotNull(position);

    for (Point point : position) {

        assertEquals(14.000001847743988d, point.getX(), 4);

        assertEquals(30.000000249977013d, point.getY(), 4);

        log.info("Position : {} x {}", point.getX(), point.getY());

    }

}

##### opsGeo #####

Distance : 4469610.0767

Position : 14.000001847743988 x 30.000000249977013

HyperLogLog structure command – 집합의 원소의 개수 추정, 타입은 string으로 저장.

redis command pfadd, pfcount에 대한 내용입니다.

@Test

public void opsHyperLogLog() {

    HyperLogLogOperations<String, String> hyperLogLogOps = redisTemplate.opsForHyperLogLog();

    String cacheKey = "valueHyperLogLog";

    String[] arr1 = {"1", "2", "2", "3", "4", "5", "5", "5", "5", "6", "7", "7", "7"};

    hyperLogLogOps.add(cacheKey, arr1);

    log.info("##### opsHyperLogLog #####");

    log.info("count : {}", hyperLogLogOps.size(cacheKey));

    redisTemplate.delete(cacheKey);

}

##### opsHyperLogLog #####

count : 7

최신 소스는 GitHub 사이트를 참고해 주세요.
https://github.com/codej99/SpringRedisCluster/tree/feature/rediscluster

 

 

[출처] https://daddyprogrammer.org/post/2241/redis-spring-data-redis-cluster-structure-comands/

728x90