개발/Spring

Part.2 Spring boot 갯수 제한 이벤트 구현(Redis 이용) Redisson, Transaction, Sync(lock) 유저가 많이 몰릴때.

JangHC 2022. 4. 6. 21:01

Part.1 에서 싱크를 걸었기 때문에 유저가 많이 몰릴경우 속도가 많이 느려진다.

 

그래서 Lock 영역에서 막는 것은 Redis로 처리하고 db insert 처리는 thread 로 처리한다.

 

 

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

import org.redisson.api.RBucket;
import org.redisson.api.RTransaction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;


@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService
{
	private final MyRedis myRedis;
	private final AsyncService asyncService;
	@Override
	public boolean temp() {
		String lock = "lock_key"; // 해당 키에만 lock을 걸고 싶으면 value를 key로
		boolean ret = false;
		try {
            if (myRedis.tryLock(lock, TimeUnit.SECONDS, 5L, 10L)) {
            	int num = Integer.parseInt((String) myRedis.getValue("key")));
        		if(num >= 1000)
        		{
        			ret =  false;
        		}
                myRedis.setValue("key",++num);
                Temp temp = new Temp();
                asyncService.asyncInsertTemp(temp);
            }
        } catch (Exception e) {
            e.getStackTrace();
            ret = false;
        } finally {
           if (myRedis.canUnlock(lock)) {
        	  myRedis.unlock(lock);
    	   } 
        }
		return ret;
	}
}
public interface AsyncServiceTemp {
	public void asyncInsertTemp(Temp temp);
}
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional
public class AsyncServiceImpl implements AsyncService {
	private final TempRepository tempRepository;
	@Override
	public void asyncInsertTemp(Temp temp) {
		tempRepository.saveAndFlush(temp);
	}
}

 

Config 추가. Thread 개수는 ec2 spec에 맞춰서 설정. (DB pool 갯수에도 영향이 갑니다)

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(100);
        executor.setMaxPoolSize(200);
        executor.setQueueCapacity(2000);
        executor.setThreadNamePrefix("lesserafim-db-async");
        executor.initialize();
        return executor;
    }
}