레디스에서 회원 데이터를 저장/조회

This commit is contained in:
assu10
2020-10-03 18:38:55 +09:00
parent 172667004a
commit b569b62569
9 changed files with 191 additions and 9 deletions

View File

@@ -226,6 +226,34 @@ springCloudBus
-- 메시지 발행/수신 확인
[POST] http://localhost:8090/member/assu
-- 레디스 설치확인
C:\Users\ju>netstat -an|findstr 6379
TCP 127.0.0.1:6379 0.0.0.0:0 LISTENING
C:\Users\ju>redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set key value
OK
127.0.0.1:6379> get key
"value"
127.0.0.1:6379>
-- 레디스 실행
redis-server.bat 실행
-- 모든 키 확인
127.0.0.1:6379> keys *
1) "member"
-- key-value 확인 (get 은 String 만 다루므로 여기선 에러로 표시)
127.0.0.1:6379> get member
(error) WRONGTYPE Operation against a key holding the wrong kind of value
-- 모든 키 삭제
127.0.0.1:6379> flushall
OK
```

View File

@@ -67,7 +67,6 @@ public class EventServiceApplication {
/**
* 레디스 서버에 작업 수행 시 사용할 RedisTemplate 객체 생성
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate() {

View File

@@ -0,0 +1,89 @@
package com.assu.cloud.eventservice.client;
import com.assu.cloud.eventservice.config.CustomConfig;
import com.assu.cloud.eventservice.model.Member;
import com.assu.cloud.eventservice.repository.MemberRedisRepository;
import com.assu.cloud.eventservice.utils.CustomContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
/**
* 회원 데이터 필요 시 회원 서비스 호출 전 레디스 캐시 먼저 확인
*/
@Component
public class MemberCacheRestTemplateClient {
private static final Logger logger = LoggerFactory.getLogger(MemberCacheRestTemplateClient.class);
private final RestTemplate restTemplate;
private final MemberRedisRepository memberRedisRepository;
private final CustomConfig customConfig;
public MemberCacheRestTemplateClient(RestTemplate restTemplate, MemberRedisRepository memberRedisRepository, CustomConfig customConfig) {
this.restTemplate = restTemplate;
this.memberRedisRepository = memberRedisRepository;
this.customConfig = customConfig;
}
String URL_PREFIX = "/api/mb/member/"; // 회원 서비스의 주울 라우팅경로와 회원 클래스 주소
/**
* 회원 아이디로 레디스에 저장된 Member 클래스 조회
*/
private Member checkRedisCache(String userId) {
try {
return memberRedisRepository.findMember(userId);
} catch (Exception e) {
logger.error("======= Error encountered while trying to retrieve member {} check Redis Cache., Exception {}", userId, e);
return null;
}
}
/**
* 레디스 캐시에 데이터 저장
*/
private void cacheMemberObject(Member member) {
try {
memberRedisRepository.saveMember(member);
} catch (Exception e) {
e.printStackTrace();
logger.error("======= Unable to cache member {} in Redis. Exception {}", member.getId(), e);
}
}
public Member getMember(String userId) {
Member member = checkRedisCache(userId);
// 레디스에 데이터가 없다면 원본 데이터에서 데이터를 조회하기 위해 회원 서비스 호출
if (member != null) {
logger.debug("======= Successfully retrieved an Member {} from the redis cache: {}", userId, member);
return member;
}
logger.debug("======= Unable to locate member from the redis cache: {}", userId);
ResponseEntity<Member> restExchange =
restTemplate.exchange(
"http://" + customConfig.getServiceIdZuul() + URL_PREFIX + "{userId}", // http://localhost:5555/api/mb/member/userInfo/rinda
HttpMethod.GET,
null,
Member.class,
userId
);
// 캐시 레코드 저장
member = restExchange.getBody();
// 조회한 객체를 캐시에 저장
if (member != null) {
cacheMemberObject(member);
}
return member;
}
}

View File

@@ -1,8 +1,10 @@
package com.assu.cloud.eventservice.controller;
import com.assu.cloud.eventservice.client.MemberCacheRestTemplateClient;
import com.assu.cloud.eventservice.client.MemberRestTemplateClient;
import com.assu.cloud.eventservice.client.MemberFeignClient;
import com.assu.cloud.eventservice.config.CustomConfig;
import com.assu.cloud.eventservice.model.Member;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -15,11 +17,14 @@ public class EventController {
private final CustomConfig customConfig;
private final MemberFeignClient memberFeignClient;
private final MemberRestTemplateClient memberRestTemplateClient;
private final MemberCacheRestTemplateClient memberCacheRestTemplateClient;
public EventController(CustomConfig customConfig, MemberFeignClient memberFeignClient, MemberRestTemplateClient memberRestTemplateClient) {
public EventController(CustomConfig customConfig, MemberFeignClient memberFeignClient, MemberRestTemplateClient memberRestTemplateClient,
MemberCacheRestTemplateClient memberCacheRestTemplateClient) {
this.customConfig = customConfig;
this.memberFeignClient = memberFeignClient;
this.memberRestTemplateClient = memberRestTemplateClient;
this.memberCacheRestTemplateClient = memberCacheRestTemplateClient;
}
@GetMapping(value = "name/{nick}")
@@ -49,6 +54,14 @@ public class EventController {
return "[EVENT] Gift is " + gift;
}
/**
* 레디스 캐싱 데이터 사용
*/
@GetMapping(value = "{userId}")
public Member userInfo(@PathVariable("userId") String userId) {
return memberCacheRestTemplateClient.getMember(userId);
}
/*@GetMapping("userInfo/{name}")
public String userInfo(@PathVariable("name") String name) {
return "[EVENT-MEMBER] " + memberRestTemplateClient.userInfo(name);

View File

@@ -2,6 +2,9 @@ package com.assu.cloud.eventservice.repository;
import com.assu.cloud.eventservice.model.Member;
/**
* 레디스에 액세스해야 하는 클래스에 주입된 인터페이스
*/
public interface MemberRedisRepository {
void saveMember(Member member);
void updateMember(Member member);

View File

@@ -1,30 +1,38 @@
package com.assu.cloud.eventservice.repository;
import com.assu.cloud.eventservice.model.Member;
import com.netflix.discovery.converters.Auto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
/**
* 부트스트랩 클래스에서 정의한 RedisTemplate 빈을 사용하여 레디스 서버와 통신
*/
@Repository
public class MemberRedisRepositoryImpl implements MemberRedisRepository {
private static final String HASH_NAME = "member"; // 회원 데이터가 저장되는 레디스 서버의 해시명
private RedisTemplate<String, Member> redisTemplate;
private final RedisTemplate<String, Member> redisTemplate;
private HashOperations hashOperations; // HashOperation 클래스는 레디스 서버에 데이터 작업을 수행하는 스프링 헬퍼 메서드의 집합
public MemberRedisRepositoryImpl() {
super();
}
public MemberRedisRepositoryImpl(RedisTemplate<String, Member> redisTemplate) {
public MemberRedisRepositoryImpl(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@PostConstruct
public void init() {
hashOperations = redisTemplate.opsForHash();
// 키와 값을 명시적으로 직렬화해주지 않으면 default serializer 로 JdkSerializationRedisSerializer 를 사용하는데
// 그러면 \xac\xed\x00\x05t\x00\x06member 이런 식으로 저장됨
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
}
@Override

View File

@@ -15,5 +15,5 @@ spring:
brokers: localhost
#redis
redis:
server: redis
server: localhost
port: 6379

View File

@@ -3,6 +3,9 @@ package com.assu.cloud.memberservice.controller;
import com.assu.cloud.memberservice.client.EventRestTemplateClient;
import com.assu.cloud.memberservice.config.CustomConfig;
import com.assu.cloud.memberservice.event.source.SimpleSourceBean;
import com.assu.cloud.memberservice.model.Member;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletRequest;
@@ -11,6 +14,8 @@ import javax.servlet.ServletRequest;
@RequestMapping("/member")
public class MemberController {
private static final Logger logger = LoggerFactory.getLogger(MemberController.class);
private final CustomConfig customConfig;
private final EventRestTemplateClient eventRestTemplateClient;
private final SimpleSourceBean simpleSourceBean;
@@ -60,4 +65,17 @@ public class MemberController {
simpleSourceBean.publishMemberChange("SAVE", userId);
}
/**
* 이벤트 서비스에서 캐시 용도로 회원 데이터 조회
*/
@GetMapping("{userId}")
public Member userInfoCache(@PathVariable("userId") String userId) {
logger.debug("====== 회원 서비스 호출!");
// DB 를 조회하여 회원 데이터 조회 (간편성을 위해 아래와 같이 리턴함)
Member member = new Member();
member.setId(userId);
member.setName("rinda");
return member;
}
}

View File

@@ -0,0 +1,24 @@
package com.assu.cloud.memberservice.model;
import java.io.Serializable;
public class Member implements Serializable {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}