상세한 서버 설정 항목인 Replication 설정과 Cluster 서비스 설정에 대해서는 추후 따로 포스팅한다.
이번 포스팅에서 캐쉬용도로 사용하는 방식과 No-SQL DB로 CRUD를 처리하는 방법을 간단하게 기술한다.
먼저 사용자 정보를 담는 Dto를 설계한다. Dto를 설계 할 때 Redis에 담겨지는 Object는 반드시 Serializable 인터페이스를 상속 받아야 한다. 직렬화 되지 않은 객체는 Redis에서 반환할 때 원래 객체로 반환 할 수 없다.
public class User implements Serializable{ private String userName; private String phoneNumber; private String email; private String address; private int userID; public int getUserID() { return userID; } public void setUserID(int userID) { this.userID = userID; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
그리고 CRUD 작업을 수행할 간단한 인터페이스를 하나 생성한다.
public interface UserAccessService { public User getUser(int id); public void setUser(User user); public User deleteUser(User User); public void updateUser(int id, User updateUser); }
Redis는 기본적으로 Key , Value를 저장하는 데이터 타입에서 자유롭다 개발자의 취향에 따라서 제네릭으로 인터페이스를 구성하는 방법도 가능하다.
public interface UserAccessService{ public User getUser(K key); public void setUser(V user); public User deleteUser(V User); public void updateUser(K key, V updateUser); }
이 예제에서는 제너릭을 사용하지 않고 진행한다.
UserAccessService를 상속 받는 2개의 클래스를 생성한다.
첫 번째 Dao는 캐쉬를 지원하는 형태로 구성한다.
캐쉬로 Redis를 사용할 때는 Spring 에서 지원하는 기본 Cache Annotation을 숙지해야 한다.
아래의 링크에서 기본 개념과 사용방법을 숙지하자. http://blog.outsider.ne.kr/1094
@Repository("userDaoCache") public class UserDaoCache implements UserAccessService { // 임의의 Database로 가정 private static HashMap<Integer, User> USERMAP = new HashMap<Integer, User>(); /*private HashMap<Integer, User> getUserMap() { if (userMap == null) userMap = new HashMap<Integer, User>(); return userMap; }*/ public UserDaoCache() { } @Override @Cacheable(value = "users", key = "#id") public User getUser(int id) { User user = USERMAP.get(id); System.out.println("This user is come from HashMap : " + user.getUserName()); return user; } @Override public void setUser(User user) { USERMAP.put(user.getUserID(), user); } @Override @CacheEvict(value = "users", allEntries=true) public User deleteUser(User user) { USERMAP.remove(user.getUserID()); return null; } @Override @CacheEvict(value = "users", allEntries=true) public void updateUser(int id, User updateUser) { USERMAP.replace(id, updateUser); } }
두 번째 Dao는 Redis 자체를 no-sql 데이터 저장소로 사용하는 방식이다.
@Repository("userDaoTemplate") public class UserDaoTemplate implements UserAccessService { @Autowired private RedisTemplate<Integer, User> redisTemplate; public UserDaoTemplate() { } @Override public User getUser(int id) { User user = redisTemplate.opsForValue().get(id); return user; } @Override public void setUser(User user) { redisTemplate.opsForValue().set(user.getUserID(), user); } @Override public User deleteUser(User User) { redisTemplate.delete(User.getUserID()); return User; } @Override public void updateUser(int id, User updateUser) { redisTemplate.opsForValue().getAndSet(id, updateUser); } }
Redis Template은 Redis에서 지원하는 자료형에 맞게 Ops 함수를 제공한다.
Redis에서 지원하는 자료형 종류를 먼저 확인하자
아래의 링크에서 지원하는 자료형을 확인 할 수 있다. Template 에서는 각 자료형 대로 저장할 수 있도록 오퍼레이터 함수를 지원한다.
http://redis.io/topics/data-types
Redis Crud를 하기 위한 준비가 끝났다.
Cache dao가 동작하는 지 확인하는 Junit 테스트 코드를 설계한다.
@Autowired @Qualifier("userDaoCache") private UserAccessService redisCache; @Test public void testCache() { User user = new User(); user.setUserID(1); user.setUserName("john"); redisCache.setUser(user); user = redisCache.getUser(1); System.out.println("Result : " + user.getUserName()); user = redisCache.getUser(1); System.out.println("Result : " + user.getUserName()); user = redisCache.getUser(1); System.out.println("Result : " + user.getUserName()); user.setUserName("tommy"); redisCache.updateUser(1, user); user = redisCache.getUser(1); System.out.println("Result : " + user.getUserName()); user = redisCache.getUser(1); System.out.println("Result : " + user.getUserName()); user = redisCache.getUser(1); System.out.println("Result : " + user.getUserName()); redisCache.deleteUser(user); }
실행결과는 다음과 같다.
처음 데이터를 읽을 때는 선언한 hashMap 안에 데이터가 출력된다.
이후에 출력되는 데이터는 Cache 에 미리 저장된 데이터가 출력됨을 알 수 있다.
이후에 사용자 정보가 Update 되면 저장된 캐쉬가 초기화 되고 다시 저장된다.
다시 저장된 캐쉬 값이 getuser 함수를 통해서 전달 되는 것을 확인할 수 있다.
두 번째 No-SQL 저장소로 구현된 Dao 가 동작하는 테스트 코드를 설계한다.
@Autowired @Qualifier("userDaoTemplate") private UserAccessService redisTemplate; @Test public void testRedis() { User user = new User(); user.setUserID(1); user.setUserName("john"); redisTemplate.setUser(user); User userfromRedis = redisTemplate.getUser(1); assertThat(user.getUserName(), org.hamcrest.core.Is.is(userfromRedis.getUserName())); user.setUserName("tommy"); redisTemplate.updateUser(1, user); userfromRedis = redisTemplate.getUser(1); assertThat(user.getUserName(), org.hamcrest.core.Is.is(userfromRedis.getUserName())); redisTemplate.deleteUser(user); userfromRedis = redisTemplate.getUser(1); }수행의 결과를 확인해보자. 설정에 문제가 없을 경우 정상적으로 Junit 테스트가 실행될 것이다. Dao 코드를 구성하기 전에 redis cli를 이용하여 구성하려는 Dao가 정상적으로 동작하는 지 확인해보는 것이 좋다. 소스 코드 위치 https://github.com/wargen99/wargen-repo.git 다음 포스팅에서는 Spring session과 Redis를 이용하여 분산환경에서 일관된 세션 유지 방법에 대해 포스팅한다.
댓글 없음:
댓글 쓰기