当前位置:网站首页>Seckill system 2 redis solves the problem of distributed session
Seckill system 2 redis solves the problem of distributed session
2022-07-03 15:21:00 【You are my forever bug】
Preface
If you operate on one Tomcat On , There is no problem , But when we deploy multiple systems , coordination Nginx There will be a problem of user login .
reason
because Nginx Use a load balancing policy , Distribute the request to the backend ,
in other words , stay Tomcat 1 After logging in , User information exists Tomcat1 Of Session in , The next request is coming Tomcat2 On , At this time Tomcat2 On Session There is no user information in , I'm going to log in .
solve
redis Installation tutorial self-study
Redis Implement distributed Session
Method 1、 Use SpringSession Realization ( This method can't jump to the page )
1、 Add dependency :
<!-- spring data redis rely on -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- commons-pool2 Object pool dependency -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- spring-session rely on -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
2、 To configure Redis
spring:
# thymeleaf Turn off caching
thymeleaf:
cache: false
# MySql Data source configuration
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/secKill?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
# Fastest connection pool
hikari:
# The name of the connection pool
pool-name: DateHikariCP
# Minimum number of idle connections
minimum-idle: 5
# Maximum free connection lifetime Default 600000(10 minute )
idle-timeout: 1800000
# maximum connection Default 10
maximum-pool-size: 10
# Connections returned from the connection pool are automatically submitted
auto-commit: true
# Maximum connection lifetime 0 For permanent survival , Default 1800000( minute )
max-lifetime: 1800000
# Connection timeout Default 30000(30 second )
connection-timeout: 30000
# A query statement to test whether the connection is possible
connection-test-query: SELECT 1
# Redis To configure
redis:
host: 127.0.0.1
port: 6379
# Database used 0
database: 0
# Connection timeout
timeout: 10000ms
lettuce:
# Configuration of connection pool
pool:
# maximum connection 8
max-active: 8
# Maximum connection blocking time
max-wait: 10000ms
# Maximum free connection
max-idle: 200
# Minimum free connection
min-idle: 5
# mybatis-plus To configure
mybatis-plus:
# To configure Mapper.xml The path of the mapping file
mapper-locations: classpath*:/mapper/*.xml # mybatis SQL Print ( Interface method in package , No mapper.xml The bag where it is ) logging: level: com.example.seckill.mapper: DEBUG
This is the time Just OK 了 , After logging in ,Session It will be saved Redis - 0( library ) -spring Session in
here Comment out the
// /**
// * After verifying the user successfully, generate cookie, take cookie Save with the user session in
// */
// // Use UUID Generate cookie
// String cookie = UUIDUtil.uuid();
// // take cookie Save with the user session in
// request.getSession().setAttribute(cookie,user);
// // Set up cookie
// CookieUtil.setCookie(request,response,"userCookie",cookie);
Log in again Discovery will also be saved Redis in .
Method 2、 Save user information in redis in
1、 Add dependency
<!-- spring data redis rely on -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- commons-pool2 Object pool dependency -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2、redis Configuration of And methods 1 equally
3、Redsi Configuration class
package com.example.seckill.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/** * Redis To configure */
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
//key serialize
redisTemplate.setKeySerializer(new StringRedisSerializer());
//value serialize
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//hash type value serialize
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
// Injection connection factory
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}
4、json Tool class
This is very important , If not from redis From user The information does not match , I can't jump Product page
package com.example.seckill.util;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.List;
/** * Json Tool class * * @author zhoubin * @since 1.0.0 */
public class JsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
/** * Converts an object to json character string * * @param obj * @return */
public static String object2JsonStr(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
// Print exception information
e.printStackTrace();
}
return null;
}
/** * Convert a string to an object * * @param <T> Generic */
public static <T> T jsonStr2Object(String jsonStr, Class<T> clazz) {
try {
return objectMapper.readValue(jsonStr.getBytes("UTF-8"), clazz);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/** * take json Data to pojo object list * <p>Title: jsonToList</p> * <p>Description: </p> * * @param jsonStr * @param beanType * @return */
public static <T> List<T> jsonToList(String jsonStr, Class<T> beanType) {
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = objectMapper.readValue(jsonStr, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
5、 modify UserServiceImpl Code
After verifying the user , take user Put in redis
And add through cookie obtain user Methods
package com.example.seckill.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.seckill.common.RespBean;
import com.example.seckill.common.RespBeanEnum;
import com.example.seckill.controller.parm.LoginRequestParam;
import com.example.seckill.exception.GlobalException;
import com.example.seckill.mapper.UserMapper;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IUserService;
import com.example.seckill.util.CookieUtil;
import com.example.seckill.util.JsonUtil;
import com.example.seckill.util.MD5Util;
import com.example.seckill.util.UUIDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** * <p> * User table Service implementation class * </p> * * @author jobob * @since 2022-06-13 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Autowired(required = false)
UserMapper userMapper;
@Autowired
private RedisTemplate redisTemplate;
@Override
public RespBean doLogin(LoginRequestParam param, HttpServletRequest request, HttpServletResponse response) {
String password = param.getPassword();
String mobile = param.getMobile();
User user = userMapper.selectById(mobile);
if (null == user){
throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
}
if (!MD5Util.formPassToDBPass(password,user.getSalt()).equals(user.getPassword())){
throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
}
/** * After verifying the user successfully, generate cookie, take cookie Save with the user session in */
// Use UUID Generate cookie
String cookie = UUIDUtil.uuid();
// take cookie Save with the user session in
// request.getSession().setAttribute(cookie,user);
redisTemplate.opsForValue().set("user:" + cookie, JsonUtil.object2JsonStr(user));
// Set up cookie
CookieUtil.setCookie(request,response,"userCookie",cookie);
return RespBean.success(cookie);
}
@Override
public User getUserByCookie(String cookie, HttpServletRequest request, HttpServletResponse response) {
if (StringUtils.isEmpty(cookie)){
return null;
}
String userJson = (String) redisTemplate.opsForValue().get("user:" + cookie);
User user = JsonUtil.jsonStr2Object(userJson, User.class);
if (null != user){
// Set up cookie
CookieUtil.setCookie(request,response,"userCookie",cookie);
}
return user;
}
}
6、 goods Controller
package com.example.seckill.controller;
import com.example.seckill.common.RespBean;
import com.example.seckill.controller.parm.LoginRequestParam;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IGoodsService;
import com.example.seckill.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@RequestMapping("/goods")
@Controller
@Slf4j
public class GoodsController {
@Autowired
IGoodsService goodsService;
@Autowired
IUserService userService;
/** * Jump to product page * @param * @param model * @param cookie * @return */
@RequestMapping("/toList")
public String toList(HttpServletRequest request, HttpServletResponse response, Model model, @CookieValue("userCookie") String cookie){
if (StringUtils.isEmpty(cookie)){
// If cookie by empty Jump to The login page
return "login";
}
// from session Get users
// User user = (User) session.getAttribute(cookie);
User user = userService.getUserByCookie(cookie, request, response);
if (null == user){
// If the user information is empty Jump to login
return "login";
}
// Put user information To the front page
model.addAttribute("user",user);
return "goodsList";
}
}
Avoid completing each interface above according to Cookie obtain User Information , Avoid code redundancy , Special optimization :
1、UserArgumentResolvers class
package com.example.seckill.config;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IUserService;
import com.example.seckill.util.CookieUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** * Custom user parameters */
@Component
public class UserArgumentResolvers implements HandlerMethodArgumentResolver {
@Autowired
IUserService userService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> parameterType = parameter.getParameterType();
return parameterType == User.class;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
String cookie = "486ceb27176a485f85e3c3d1f4f35e77";
// String cookie = CookieUtil.getCookieValue(request, "userCookie");
if (StringUtils.isEmpty(cookie)){
// If cookie by empty Jump to The login page
return null;
}
return userService.getUserByCookie(cookie, request, response);
}
}
2、
package com.example.seckill.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/** * MVC Configuration class * */
@Configuration
//@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Autowired
UserArgumentResolvers userArgumentResolvers;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers){
resolvers.add(userArgumentResolvers);
}
}
3、goodController
package com.example.seckill.controller;
import com.example.seckill.common.RespBean;
import com.example.seckill.controller.parm.LoginRequestParam;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IGoodsService;
import com.example.seckill.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@RequestMapping("/goods")
@Controller
@Slf4j
public class GoodsController {
@Autowired
IGoodsService goodsService;
@Autowired
IUserService userService;
/** * Jump to product page * @param * @param model * @param * @return */
@RequestMapping("/toList")
public String toList(Model model,User user){
// Put user information To the front page
model.addAttribute("user",user);
return "goodsList";
}
}
problem : Here I have a problem , Each generation Cookie Put in Redis It's normal , But call other interfaces after successful login adopt CookieUtil Acquired Cookie Not generated by this login Cookie It's annoying ~ I don't know much about this So I'm making sure that redis There is this cookie , take cookie It's dead
边栏推荐
- Solve the problem that pushgateway data will be overwritten by multiple push
- Puppet automatic operation and maintenance troubleshooting cases
- Calibre LVL
- XWiki Installation Tips
- Puppet自动化运维排错案例
- 官网MapReduce实例代码详细批注
- 第04章_逻辑架构
- Jvm-04-runtime data area heap, method area
- Concurrency-01-create thread, sleep, yield, wait, join, interrupt, thread state, synchronized, park, reentrantlock
- redis缓存穿透,缓存击穿,缓存雪崩解决方案
猜你喜欢
秒杀系统1-登录功能
Kubernetes will show you from beginning to end
[cloud native training camp] module 7 kubernetes control plane component: scheduler and controller
运维体系的构建
Kubernetes 进阶训练营 Pod基础
Kubernetes vous emmène du début à la fin
【云原生训练营】模块八 Kubernetes 生命周期管理和服务发现
【云原生训练营】模块七 Kubernetes 控制平面组件:调度器与控制器
Chapter 04_ Logical architecture
视觉上位系统设计开发(halcon-winform)-4.通信管理
随机推荐
Functional modules and application scenarios covered by the productization of user portraits
Final review points of human-computer interaction
Global and Chinese markets for indoor HDTV antennas 2022-2028: Research Report on technology, participants, trends, market size and share
The state does not change after the assignment of El switch
Dataframe returns the whole row according to the value
[attention mechanism] [first vit] Detr, end to end object detection with transformers the main components of the network are CNN and transformer
Kubernetes - yaml file interpretation
Nppexec get process return code
The first character of leetcode sword offer that only appears once (12)
Visual host system design and development (Halcon WinForm)
Leetcode sword offer find the number I (nine) in the sorted array
Stress test WebService with JMeter
What is machine reading comprehension? What are the applications? Finally someone made it clear
Jvm-09 byte code introduction
[pytorch learning notes] datasets and dataloaders
Redis lock Optimization Practice issued by gaobingfa
Visual upper system design and development (Halcon WinForm) -6 Nodes and grids
【pytorch学习笔记】Transforms
秒杀系统2-Redis解决分布式Session问题
Visual upper system design and development (Halcon WinForm) -2 Global variable design