Springboot+mysql+redis实现简单的多人抢单 秒杀 详细代码 项目源码

前话
同时使用@Transactional注解和 synchronized或者同时使用@Transactional注解和和分布式锁会造成线程安全问题,因为@Transactional是用AOP实现的,当synchronized里面的方法运行完后,AOP的代码里面的事务提交可能还没运行,此时其他请求可以进去synchronized运行,结果就读到了还未提交的事务的数据,去掉@Transactional注解,使用手动开启事务,并提交,将所有代码都放在 synchronized里面,但是synchronized只能再单击起作用,多机只能使用分布式锁

方案一
使用mysql自带的for update
这样在第一次修改完成前 第二次无法查询 自然就可以保证库存减少和订单数相同

方案二
抢单前将库存查询到redis中 使用redis的decrement来保证库存减少的原子性
然后用定时任务每隔一段时间将redis库存同步到mysql中

方案三
使用synchronized,只能在单机起作用

方案四
使用分布式锁

方案五
使用一条update代替select加update,依靠返回的影响行数,判断有无减库存成功,先查询再根据查询的值来update,由于查询是并发的,查询到快照或者说不是最新版本的值,再更新值就会出问题,但是并发update的话,数据库可以保证加上互斥锁,来保证操作原子,就算不是互斥锁,也会在快照并发修改后进行有效性检验

项目代码 https://gitee.com/chen_yan_ting/springboot_grabbing_orders

数据表结构
在这里插入图片描述
本次简单测试只用到两张表 六个字段

项目结构
在这里插入图片描述
引入依赖
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima</groupId>
    <artifactId>springboot_grabbing_orders</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <!-- mybatis plus 代码生成器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>
</project>

配置文件
application.yml

server:
  port: 9000
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/grabbing_orders?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
    username: root
    password:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    serialization:
      write-dates-as-timestamps: false
  redis:
    port: 6379
mybatis-plus:
  mapper-locations: classpath*:mapper/**/*Mapper.xml
logging.level.com.itheima.mapper: debug #配置显示执行的sql语句

mybatis-plus构造器代码
运行main 输入表名 自动连接数据库 构造代码
GeneratorCodeConfig.java

package com.itheima.config;

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.Scanner;

public class GeneratorCodeConfig {
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入"+ tip + ": ");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                scanner.close();;
                return ipt;
            }
        }
        scanner.close();
        throw new MybatisPlusException("请输入正确的"+ tip);
    }

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        // 获取系统参数 当前目录
        String projectPaht = System.getProperty("user.dir");
        gc.setOutputDir(projectPaht+"/src/main/java");
        gc.setAuthor("astupidcoder");
        gc.setOpen(false);
        // 实体属性 Swagger2 注解
        gc.setSwagger2(false);
        mpg.setGlobalConfig(gc);

        //数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://127.0.0.1:3306/grabbing_orders?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("");
        mpg.setDataSource(dsc);

        // pc.setModuleName(scanner("模块名"));
        // 包配置
        PackageConfig pc = new PackageConfig();
        pc
                .setParent("com.itheima")
                .setEntity("model")
                .setMapper("mapper")
                .setService("service")
                .setServiceImpl("service.impl");
        mpg.setPackageInfo(pc);

        // 自定义配置
        //        InjectionConfig cfg = new InjectionConfig() {
//            @Override
//            public void initMap() {
//                // to do nothing
//            }
//        };
        // 如果模板引擎是 freemarker
//        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
//        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
//        focList.add(new FileOutConfig(templatePath) {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
//                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
//                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
//            }
//        });
        /*
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判断自定义文件夹是否需要创建
                checkDir("调用默认方法创建的目录");
                return false;
            }
        });
        */
//        cfg.setFileOutConfigList(focList);
//        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定义输出模板
        //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        // templateConfig.setEntity("templates/entity2.java");
        // templateConfig.setService();
        // templateConfig.setController();

        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setSuperEntityClass("com.baomidou.mybatisplus.extension.activerecord.Model");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setEntityLombokModel(true);

        // 公共父类
//        strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController");
        // 写于父类中的公共字段
//        strategy.setSuperEntityColumns("id");
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}

代码生成完成后我们要改的文件有
TSeckillArticleMapper 操作数据库
TOrderServiceImpl 业务逻辑实现类
ITOrderService 业务逻辑接口
TOrderController 接收请求
OrdersApplication 启动文件
RedisTemplateConfig 配置StringRedisSerializer 序列化方式 否则无法使用decrement

OrdersApplication.java

package com.itheima;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@MapperScan("com.itheima.mapper") //配置mapper包扫描路径
@EnableScheduling
public class OrdersApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrdersApplication.class, args);
    }
}

ITOrderService.java

package com.itheima.service;

import com.itheima.model.TOrder;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author astupidcoder
 * @since 2021-05-15
 */
public interface ITOrderService extends IService<TOrder> {
    String POrder1(String userId, String arcId, String totalPrice) throws Exception;

    String initializationStockNum(String articleId);
}

TOrderServiceImpl.java

package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.itheima.mapper.TSeckillArticleMapper;
import com.itheima.model.TOrder;
import com.itheima.mapper.TOrderMapper;
import com.itheima.model.TSeckillArticle;
import com.itheima.service.ITOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Wrapper;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author astupidcoder
 * @since 2021-05-15
 */
@Service
@Transactional
public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> implements ITOrderService {

    @Autowired
    private TOrderMapper tOrderMapper;

//    //Reentrant可重入 Locak锁
//    private Lock lock = new ReentrantLock();

    @Autowired
    private TSeckillArticleMapper tSeckillArticleMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    private static AtomicInteger count = new AtomicInteger(0);

    private static final Long SUCCESS = 1L;
    // 获取锁的超时时间
    private static final long timeout = 10000;

    /**
     * @author 陈衍汀
     * @Date 2021/5/15 22:08
     * @param userId 用户编号
     * @param arcId 商品编号
     * @param totalPrice 订单总额
     * @return java.lang.String
     * @Description
    */
    @Override
    public synchronized String POrder1(String userId, String arcId, String totalPrice) throws Exception {
        // 先将库存减一 再返回
        Long articleStockNum = redisTemplate.opsForValue().decrement("order_" + arcId);

        if (articleStockNum > -1) {
            //进行下单
            TOrder tOrder = new TOrder();
            tOrder.setId(UUID.randomUUID().toString().substring(10));
            tOrder.setUserId(userId);
            tOrder.setArticleId(arcId);
            tOrder.setAddTime(LocalDateTime.now());
            tOrder.setOrderStatus(0);
            // 往订单表添加订单
            tOrderMapper.insert(tOrder);
            return "下单成功";
        } else {
            return "库存不足";
        }
    }

    @Override
    public String initializationStockNum(String articleId) {
    	//通过商品ID查询库存并存入redis中
        TSeckillArticle tSeckillArticle = tSeckillArticleMapper.selectStockNumByArticleId(articleId);
        Integer articleStockNum = tSeckillArticle.getArticleStockNum();
        redisTemplate.opsForValue().setIfAbsent("order_"+articleId, articleStockNum+"", 5, TimeUnit.MINUTES);
        return "初始化成功";
    }

	//每隔10秒运行一次
    @Scheduled(cron = "0/10 * * * * ?")
    public void synchronizationStockNum() {
        // 查询reids库存 并修改mysql的库存 同步
        String articleStockNum = (String)redisTemplate.opsForValue().get("order_"+100);

        if (articleStockNum != null) {
            Long l = Long.valueOf(articleStockNum);
            if (l < 0) {
                l = 0L;
            }
            TSeckillArticle tSeckillArticle = new TSeckillArticle();
            tSeckillArticle.setId("1");
            tSeckillArticle.setArticleStockNum(l.intValue());
            tSeckillArticleMapper.updateById(tSeckillArticle);
        }
    }
}

TSeckillArticleMapper.java

package com.itheima.mapper;

import com.itheima.model.TSeckillArticle;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**
 * <p>
 *  Mapper 接口
 * </p>
 *
 * @author astupidcoder
 * @since 2021-05-15
 */
public interface TSeckillArticleMapper extends BaseMapper<TSeckillArticle> {
//     for update;
    @Select("select id, articleStockNum from t_seckill_article where articleId = #{articleId}")
    TSeckillArticle selectStockNumByArticleId(@Param("articleId") String articleId);
}

TOrderController.java

package com.itheima.controller;


import com.itheima.service.ITOrderService;
import com.itheima.service.ITSeckillArticleService;
import com.itheima.service.impl.TOrderServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.websocket.server.PathParam;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author astupidcoder
 * @since 2021-05-15
 */
@RestController
@RequestMapping("/t-order")
@CrossOrigin
public class TOrderController {

    @Autowired
    private ITOrderService itOrderService;

    @Autowired
    private TOrderServiceImpl tOrderService;

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/grabbingOrders")
    public String grabbingOrders(@PathParam("articleId") String articleId) throws Exception {
    	//String POrder1(String userId, String arcId, String totalPrice)
    	//userId用户ID arcId商品ID totalPrice价格
        tOrderService.POrder1("1",articleId,"1");
        return "OK";
    }

    @GetMapping("/start")
    public String start() {
    	//"100"为商品ID
        tOrderService.initializationStockNum("100");
        return "初始化库存成功";
    }
}

RedisTemplateConfig.java

package com.itheima.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.StringRedisSerializer;

@Configuration
public class RedisTemplateConfig {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate= new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

这是方案二的全部代码
运行方法

1.在OrdersApplication启动服务器
2.在mysql中t_seckill_article表创建一行数据用来存储库存 100000为库存在这里插入图片描述
3.使用Postman请求 http://localhost:9000/t-order/start 用来查询mysql库存初始化到redis
4.使用Jmeter并发请求 http://localhost:9000/t-order/grabbingOrders?articleId=100
mysql redis postman jmeter 如何使用请百度

测试
库存99999
在这里插入图片描述

两百线程 循环300次
在这里插入图片描述
请求的URL
在这里插入图片描述

结果
TPS700每秒
在这里插入图片描述
6万次请求库存无超卖
在这里插入图片描述

方案一
修改TSeckillArticleMapper.java
添加for update 语句

package com.itheima.mapper;

import com.itheima.model.TSeckillArticle;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**
 * <p>
 *  Mapper 接口
 * </p>
 *
 * @author astupidcoder
 * @since 2021-05-15
 */
public interface TSeckillArticleMapper extends BaseMapper<TSeckillArticle> {
//     for update;
    @Select("select id, articleStockNum from t_seckill_article where articleId = #{articleId} for update;")
    TSeckillArticle selectStockNumByArticleId(@Param("articleId") String articleId);
}

修改TOrderServiceImpl.java

package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.itheima.mapper.TSeckillArticleMapper;
import com.itheima.model.TOrder;
import com.itheima.mapper.TOrderMapper;
import com.itheima.model.TSeckillArticle;
import com.itheima.service.ITOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Wrapper;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author astupidcoder
 * @since 2021-05-15
 */
@Service
@Transactional
public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> implements ITOrderService {

    @Autowired
    private TOrderMapper tOrderMapper;

//    //Reentrant可重入 Locak锁
//    private Lock lock = new ReentrantLock();

    @Autowired
    private TSeckillArticleMapper tSeckillArticleMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    private static AtomicInteger count = new AtomicInteger(0);

    private static final Long SUCCESS = 1L;
    // 获取锁的超时时间
    private static final long timeout = 10000;

    /**
     * @author 陈衍汀
     * @Date 2021/5/15 22:08
     * @param userId 用户编号
     * @param arcId 商品编号
     * @param totalPrice 订单总额
     * @return java.lang.String
     * @Description
    */
    @Override
    public synchronized String POrder1(String userId, String arcId, String totalPrice) throws Exception {
        // 从数据库查询库存
        TSeckillArticle tSeckillArticle = tSeckillArticleMapper.selectStockNumByArticleId(arcId);
        Integer articleStockNum = tSeckillArticle.getArticleStockNum();
        if (articleStockNum > 0) {
            //库存减一
            tSeckillArticle.setArticleStockNum(--articleStockNum);
            //修改数据库库存
            tSeckillArticleMapper.updateById(tSeckillArticle);

            //订单表添加订单
            TOrder tOrder = new TOrder();
            tOrder.setId(UUID.randomUUID().toString().substring(10));
            tOrder.setUserId(userId);
            tOrder.setArticleId(arcId);
            tOrder.setAddTime(LocalDateTime.now());
            tOrder.setOrderStatus(0);
            tOrderMapper.insert(tOrder);
            return "下单成功";
        }
        return "库存不足";
}

测试
1.纯DB操作 无需初始化库存到redis
2.数据库库存为5000在这里插入图片描述
3.使用Jmeter并发请求 http://localhost:9000/t-order/grabbingOrders?articleId=100

结果
200线程 20次循环 4000次请求 344TPS在这里插入图片描述
库存也没有超卖
在这里插入图片描述

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码 项目设计 系统开发 springboot vue 管理系统 小程序 源代码
回答: 从提供的引用内容来看,这是关于使用Spring BootMySQLRedis的问题。Spring Boot是一个用于快速构建基于Spring框架的应用程序的开发框架。MySQL是一个流行的关系型数据库管理系统,而Redis是一个开源的内存数据结构存储系统。 根据引用\[1\]中的内容,启动Redis服务的步骤如下: 1. 进入Redis安装目录的bin文件夹。 2. 使用命令"./redis-server /usr/local/redis/etc/redis.conf"启动Redis服务。 3. 使用命令"./redis-cli"进入Redis命令行界面。 4. 使用命令"auth 123456"进行密码登录。 引用\[2\]中提供了一个示例的配置文件,其中包含了Redis的主机、端口、密码和数据库等信息。 引用\[3\]中展示了一个UserController类的示例代码,其中包含了初始化Redis数据和通过登录名获取用户信息的方法。 综上所述,这是一个关于使用Spring BootMySQLRedis项目,其中包含了Redis的启动、配置和使用示例。 #### 引用[.reference_title] - *1* [SpringBoot整合redis+mysql](https://blog.csdn.net/qq_44715376/article/details/128040246)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [SpringBoot实践 - SpringBoot+MySql+Redis](https://blog.csdn.net/weixin_30670151/article/details/98784370)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lolxxs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值