레디스에서 회원 데이터를 저장/조회
This commit is contained in:
28
README.md
28
README.md
@@ -226,6 +226,34 @@ springCloudBus
|
|||||||
-- 메시지 발행/수신 확인
|
-- 메시지 발행/수신 확인
|
||||||
[POST] http://localhost:8090/member/assu
|
[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
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ public class EventServiceApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 레디스 서버에 작업 수행 시 사용할 RedisTemplate 객체 생성
|
* 레디스 서버에 작업 수행 시 사용할 RedisTemplate 객체 생성
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public RedisTemplate<String, Object> redisTemplate() {
|
public RedisTemplate<String, Object> redisTemplate() {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.assu.cloud.eventservice.controller;
|
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.MemberRestTemplateClient;
|
||||||
import com.assu.cloud.eventservice.client.MemberFeignClient;
|
import com.assu.cloud.eventservice.client.MemberFeignClient;
|
||||||
import com.assu.cloud.eventservice.config.CustomConfig;
|
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.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -15,11 +17,14 @@ public class EventController {
|
|||||||
private final CustomConfig customConfig;
|
private final CustomConfig customConfig;
|
||||||
private final MemberFeignClient memberFeignClient;
|
private final MemberFeignClient memberFeignClient;
|
||||||
private final MemberRestTemplateClient memberRestTemplateClient;
|
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.customConfig = customConfig;
|
||||||
this.memberFeignClient = memberFeignClient;
|
this.memberFeignClient = memberFeignClient;
|
||||||
this.memberRestTemplateClient = memberRestTemplateClient;
|
this.memberRestTemplateClient = memberRestTemplateClient;
|
||||||
|
this.memberCacheRestTemplateClient = memberCacheRestTemplateClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "name/{nick}")
|
@GetMapping(value = "name/{nick}")
|
||||||
@@ -49,6 +54,14 @@ public class EventController {
|
|||||||
return "[EVENT] Gift is " + gift;
|
return "[EVENT] Gift is " + gift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 레디스 캐싱 데이터 사용
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "{userId}")
|
||||||
|
public Member userInfo(@PathVariable("userId") String userId) {
|
||||||
|
return memberCacheRestTemplateClient.getMember(userId);
|
||||||
|
}
|
||||||
|
|
||||||
/*@GetMapping("userInfo/{name}")
|
/*@GetMapping("userInfo/{name}")
|
||||||
public String userInfo(@PathVariable("name") String name) {
|
public String userInfo(@PathVariable("name") String name) {
|
||||||
return "[EVENT-MEMBER] " + memberRestTemplateClient.userInfo(name);
|
return "[EVENT-MEMBER] " + memberRestTemplateClient.userInfo(name);
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package com.assu.cloud.eventservice.repository;
|
|||||||
|
|
||||||
import com.assu.cloud.eventservice.model.Member;
|
import com.assu.cloud.eventservice.model.Member;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 레디스에 액세스해야 하는 클래스에 주입된 인터페이스
|
||||||
|
*/
|
||||||
public interface MemberRedisRepository {
|
public interface MemberRedisRepository {
|
||||||
void saveMember(Member member);
|
void saveMember(Member member);
|
||||||
void updateMember(Member member);
|
void updateMember(Member member);
|
||||||
|
|||||||
@@ -1,30 +1,38 @@
|
|||||||
package com.assu.cloud.eventservice.repository;
|
package com.assu.cloud.eventservice.repository;
|
||||||
|
|
||||||
import com.assu.cloud.eventservice.model.Member;
|
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.HashOperations;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
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 org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 부트스트랩 클래스에서 정의한 RedisTemplate 빈을 사용하여 레디스 서버와 통신
|
||||||
|
*/
|
||||||
@Repository
|
@Repository
|
||||||
public class MemberRedisRepositoryImpl implements MemberRedisRepository {
|
public class MemberRedisRepositoryImpl implements MemberRedisRepository {
|
||||||
|
|
||||||
private static final String HASH_NAME = "member"; // 회원 데이터가 저장되는 레디스 서버의 해시명
|
private static final String HASH_NAME = "member"; // 회원 데이터가 저장되는 레디스 서버의 해시명
|
||||||
private RedisTemplate<String, Member> redisTemplate;
|
private final RedisTemplate<String, Member> redisTemplate;
|
||||||
private HashOperations hashOperations; // HashOperation 클래스는 레디스 서버에 데이터 작업을 수행하는 스프링 헬퍼 메서드의 집합
|
private HashOperations hashOperations; // HashOperation 클래스는 레디스 서버에 데이터 작업을 수행하는 스프링 헬퍼 메서드의 집합
|
||||||
|
|
||||||
public MemberRedisRepositoryImpl() {
|
public MemberRedisRepositoryImpl(RedisTemplate redisTemplate) {
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MemberRedisRepositoryImpl(RedisTemplate<String, Member> redisTemplate) {
|
|
||||||
this.redisTemplate = redisTemplate;
|
this.redisTemplate = redisTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
hashOperations = redisTemplate.opsForHash();
|
hashOperations = redisTemplate.opsForHash();
|
||||||
|
|
||||||
|
// 키와 값을 명시적으로 직렬화해주지 않으면 default serializer 로 JdkSerializationRedisSerializer 를 사용하는데
|
||||||
|
// 그러면 \xac\xed\x00\x05t\x00\x06member 이런 식으로 저장됨
|
||||||
|
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||||
|
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -15,5 +15,5 @@ spring:
|
|||||||
brokers: localhost
|
brokers: localhost
|
||||||
#redis
|
#redis
|
||||||
redis:
|
redis:
|
||||||
server: redis
|
server: localhost
|
||||||
port: 6379
|
port: 6379
|
||||||
@@ -3,6 +3,9 @@ package com.assu.cloud.memberservice.controller;
|
|||||||
import com.assu.cloud.memberservice.client.EventRestTemplateClient;
|
import com.assu.cloud.memberservice.client.EventRestTemplateClient;
|
||||||
import com.assu.cloud.memberservice.config.CustomConfig;
|
import com.assu.cloud.memberservice.config.CustomConfig;
|
||||||
import com.assu.cloud.memberservice.event.source.SimpleSourceBean;
|
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 org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
@@ -11,6 +14,8 @@ import javax.servlet.ServletRequest;
|
|||||||
@RequestMapping("/member")
|
@RequestMapping("/member")
|
||||||
public class MemberController {
|
public class MemberController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MemberController.class);
|
||||||
|
|
||||||
private final CustomConfig customConfig;
|
private final CustomConfig customConfig;
|
||||||
private final EventRestTemplateClient eventRestTemplateClient;
|
private final EventRestTemplateClient eventRestTemplateClient;
|
||||||
private final SimpleSourceBean simpleSourceBean;
|
private final SimpleSourceBean simpleSourceBean;
|
||||||
@@ -60,4 +65,17 @@ public class MemberController {
|
|||||||
simpleSourceBean.publishMemberChange("SAVE", userId);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user