国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

SpringBoot+RabbitMQ+Redis實現(xiàn)秒殺功能

這篇具有很好參考價值的文章主要介紹了SpringBoot+RabbitMQ+Redis實現(xiàn)秒殺功能。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、背景

傳統(tǒng)處理:如果不涉及到redis的話,最初的用戶請求進來的流程大概是先去數(shù)據(jù)庫判斷下當前用戶是否已經(jīng)秒殺過當前商品,如果秒殺過的話則返回秒殺失敗不能重復秒殺,否則的話則執(zhí)行減庫存,下訂單等步驟。

然而秒殺場景下,用戶量非常龐大直接訪問數(shù)據(jù)庫的可能會使服務崩潰。為了減少對數(shù)據(jù)庫的訪問,用redis進行緩存處理,這樣用戶請求過來之后不訪問數(shù)據(jù)庫而是訪問redis。我們可以使用RabbitMQ來解決用戶大量訪問帶來的問題,緩解系統(tǒng)壓力。

二、實現(xiàn)思路

  • 用戶發(fā)起秒殺請求
  • 后端服務先進行用戶身份驗證,確保請求的合法性
  • 后端服務從Redis中查詢是否存儲用戶秒殺成功的記錄,如果存在,提示只能秒殺一次
  • 后端服務從Redis中查詢商品庫存信息,如果庫存不足,則返回秒殺失敗
  • 如果庫存充足,后端服務將秒殺請求放入RabbitMQ隊列中。
  • RabbitMQ將請求分發(fā)給給消費者進行處理。
  • 消費者里進行訂單的生成、商品數(shù)量減少等操作,從而實現(xiàn)秒殺功能。

三、實現(xiàn)步驟

技術:SpringBoot、Mybatis-Plus、MySQL、Redis、RabbitMQ

1、創(chuàng)建一個SpringBoot項目,jdk選1.8

2、集成redis

添加相應的依賴

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.7.5</version>
        </dependency>

        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>6.2.2.RELEASE</version>
        </dependency>

創(chuàng)建redis工具類

package com.example.rabbitmq_03.until;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // =============================common============================
    /**
     * 指定緩存失效時間
     * @param key  鍵
     * @param time 時間(秒)
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根據(jù)key 獲取過期時間
     * @param key 鍵 不能為null
     * @return 時間(秒) 返回0代表為永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }


    /**
     * 判斷key是否存在
     * @param key 鍵
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 刪除緩存
     * @param key 可以傳一個值 或多個
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
            }
        }
    }


    // ============================String=============================

    /**
     * 普通緩存獲取
     * @param key 鍵
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通緩存放入
     * @param key   鍵
     * @param value 值
     * @return true成功 false失敗
     */

    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 普通緩存放入并設置時間
     * @param key   鍵
     * @param value 值
     * @param time  時間(秒) time要大于0 如果time小于等于0 將設置無限期
     * @return true成功 false 失敗
     */

    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 遞增
     * @param key   鍵
     * @param delta 要增加幾(大于0)
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("遞增因子必須大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }


    /**
     * 遞減
     * @param key   鍵
     * @param delta 要減少幾(小于0)
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("遞減因子必須大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }


    // ================================Map=================================

    /**
     * HashGet
     * @param key  鍵 不能為null
     * @param item 項 不能為null
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 獲取hashKey對應的所有鍵值
     * @param key 鍵
     * @return 對應的多個鍵值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     * @param key 鍵
     * @param map 對應多個鍵值
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * HashSet 并設置時間
     * @param key  鍵
     * @param map  對應多個鍵值
     * @param time 時間(秒)
     * @return true成功 false失敗
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
     *
     * @param key   鍵
     * @param item  項
     * @param value 值
     * @return true 成功 false失敗
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
     *
     * @param key   鍵
     * @param item  項
     * @param value 值
     * @param time  時間(秒) 注意:如果已存在的hash表有時間,這里將會替換原有的時間
     * @return true 成功 false失敗
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 刪除hash表中的值
     *
     * @param key  鍵 不能為null
     * @param item 項 可以使多個 不能為null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }


    /**
     * 判斷hash表中是否有該項的值
     *
     * @param key  鍵 不能為null
     * @param item 項 不能為null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }


    /**
     * hash遞增 如果不存在,就會創(chuàng)建一個 并把新增后的值返回
     *
     * @param key  鍵
     * @param item 項
     * @param by   要增加幾(大于0)
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }


    /**
     * hash遞減
     *
     * @param key  鍵
     * @param item 項
     * @param by   要減少記(小于0)
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }


    // ============================set=============================

    /**
     * 根據(jù)key獲取Set中的所有值
     * @param key 鍵
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 根據(jù)value從一個set中查詢,是否存在
     *
     * @param key   鍵
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 將數(shù)據(jù)放入set緩存
     *
     * @param key    鍵
     * @param values 值 可以是多個
     * @return 成功個數(shù)
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 將set數(shù)據(jù)放入緩存
     *
     * @param key    鍵
     * @param time   時間(秒)
     * @param values 值 可以是多個
     * @return 成功個數(shù)
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 獲取set緩存的長度
     *
     * @param key 鍵
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 移除值為value的
     *
     * @param key    鍵
     * @param values 值 可以是多個
     * @return 移除的個數(shù)
     */

    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // ===============================list=================================

    /**
     * 獲取list緩存的內(nèi)容
     *
     * @param key   鍵
     * @param start 開始
     * @param end   結束 0 到 -1代表所有值
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 獲取list緩存的長度
     *
     * @param key 鍵
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 通過索引 獲取list中的值
     *
     * @param key   鍵
     * @param index 索引 index>=0時, 0 表頭,1 第二個元素,依次類推;index<0時,-1,表尾,-2倒數(shù)第二個元素,依次類推
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 將list放入緩存
     *
     * @param key   鍵
     * @param value 值
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 將list放入緩存
     * @param key   鍵
     * @param value 值
     * @param time  時間(秒)
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }


    /**
     * 將list放入緩存
     *
     * @param key   鍵
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }


    /**
     * 將list放入緩存
     *
     * @param key   鍵
     * @param value 值
     * @param time  時間(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 根據(jù)索引修改list中的某條數(shù)據(jù)
     *
     * @param key   鍵
     * @param index 索引
     * @param value 值
     * @return
     */

    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 移除N個值為value
     *
     * @param key   鍵
     * @param count 移除多少個
     * @param value 值
     * @return 移除的個數(shù)
     */

    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}

創(chuàng)建redis配置類

package com.example.rabbitmq_03.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;


@Configuration
public class RedisConfig {
    //編寫自己的redis模板
    //固定模板
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        //我們?yōu)榉奖汩_發(fā),一般直接使用<String, Object>
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(factory);

        //Json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //string的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //Key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        //value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

修改yml文件

Spring:
  redis:
    port: 6379
    host: 本機(120.0.0.1)或者服務(ip)
    password: 密碼

3、集成RabbitMQ

添加依賴

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

創(chuàng)建rabbitmq的配置類

@Configuration
public class TopicConfig {

    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange("seckill_topic", true, false);
    }

    @Bean
    public Queue seckillQueue() {
        return new Queue("seckillQueue", true);
    }

    @Bean
    public Binding binding() {
        return BindingBuilder.bind(seckillQueue()).to(topicExchange()).with("seckill.#");
    }
}

修改yml文件

spring:
  rabbitmq:
    username: admin
    password: admin
    virtual-host: /
    host: ip
    port: 5672

4、創(chuàng)建數(shù)據(jù)庫表

用戶表

springboot集成rabbitmq redis,java-rabbitmq,spring boot,rabbitmq

商品表

springboot集成rabbitmq redis,java-rabbitmq,spring boot,rabbitmq

秒殺商品表

springboot集成rabbitmq redis,java-rabbitmq,spring boot,rabbitmq?

訂單表

springboot集成rabbitmq redis,java-rabbitmq,spring boot,rabbitmq?

秒殺訂單表

springboot集成rabbitmq redis,java-rabbitmq,spring boot,rabbitmq?

創(chuàng)建完表后,根據(jù)字段創(chuàng)建對應的pojo類、service類、mapper類。?

5、具體實現(xiàn)過程

  • 用戶登錄
  • 將要秒殺的商品數(shù)量預存在redis中
  • 接收前端傳回來的用戶id,被秒殺商品id
  • 驗證用戶是否為當前用戶,是則進行下一步
  • 獲取被秒殺的商品信息
  • 判斷用戶是否成功秒殺過商品,如果秒殺過,則結束進程,否則下一步
  • 判斷被秒殺商品是否還有庫存,有,下一步,否則結束進程
  • 將用戶id和被秒殺商品信息傳入隊列進行處理
  • 隊列處理完成后,返回結果。

秒殺接口以及每部流程的詳細代碼如下

秒殺接口

 @ApiModelProperty(value = "秒殺功能")
    @PostMapping("doseckill")
    public Result doSeckill(@RequestParam Long userid, @RequestParam Long goodsid) {
     
        //判斷是否當前用戶
        RUser user = (RUser) redisUtil.get("user" + userid + ":");
        if (user == null) {
            return Result.fail("請登錄!");
       }

        //緩存被秒殺商品的信息
        if (redisUtil.get("g" + goodsid + ":") == null) {
            GoodsVo goods = goodsService.selectGoodsById(goodsid);
            redisUtil.set("g" + goodsid + ":", goods);
        }
        GoodsVo goods = (GoodsVo) redisUtil.get("g" + goodsid + ":");

        //判斷是否重復操作,已經(jīng)成功秒殺,不能再次秒殺
//        SeckillOrders seckillOrders = seckillOrdersService.getOne(new QueryWrapper<SeckillOrders>()
//                .lambda().eq(SeckillOrders::getUserId, userid)
//                .eq(SeckillOrders::getGoodId, goods.getId()));
        Object o = redisUtil.get("order:" + userid + goodsid);
        if (o != null) {
            return Result.fail("用戶" + userid + ":每個用戶只能秒殺一次.....");
        }
        //庫存預減
        Long count = redisUtil.decr("seckill" + goodsid + ":", 1);
        if (count < 0) {
            redisUtil.incr("seckill" + goodsid + ":", 1);
            return Result.fail("用戶" + userid + ":存庫不足,秒殺失敗.....");
        }
        //將秒殺請求添加到隊列中
        MqMessage message = new MqMessage(userid, goods);
        String msg = JSON.toJSONString(message);
        product.sendSeckillMessage(msg);
        return Result.succ("秒殺中............");
    }

用戶登錄

校驗賬號和密碼是否正確,兩者都正確則登陸成功,否則登陸失敗。如果登錄成功,就將用戶的信息緩存在redis中,后續(xù)如果需要使用到用戶的信息,直接從redis中獲取即可,不用再次訪問數(shù)據(jù)庫。

public RUser Login(UserDto userDto) {
        RUser user = new RUser();
        BeanUtils.copyProperties(userDto,user);
        QueryWrapper<RUser> qw = new QueryWrapper<>();
        qw.lambda().eq(RUser::getId,user.getId())
                .eq(RUser::getPassword,user.getPassword());
        RUser user1 =baseMapper.selectOne(qw);
        if(user1!=null){
          redisUtil.set("user"+user1.getId()+":",user1);
            System.out.println(redisUtil.set("user"+user1.getId()+":",user1));
        }
        return user1;
    }

秒殺功能的流程是:獲得秒殺資格后,需要進行商品數(shù)量減少、生成訂單、生成秒殺訂單的操作,當三者都成功運行后,才能秒殺成功。

?秒殺商品數(shù)量初始化

在系統(tǒng)初始化時,調用這個方法,將秒殺商品的數(shù)量存儲在redis中,后續(xù)使用redis進行預減功能

@Override
    public void getSeckillCount() {
        List<Seckill> list = baseMapper.selectList(null);
        list.forEach(System.out::println);
        if (list.size()>0) {
            list.forEach(seckill -> {
                redisUtil.set("seckill" + seckill.getGoodsId() + ":", seckill.getStockCount());
                Object o = redisUtil.get("seckill" + seckill.getGoodsId() + ":");
                System.out.println(o.toString());
            });
        }

?rabbitmq隊列

生產(chǎn)者代碼

把用戶id和秒殺商品信息分發(fā)到隊列中

 public void sendSeckillMessage(String msg){
        System.out.println("發(fā)送秒殺信息"+msg);
        rabbitTemplate.convertAndSend("seckill_topic","seckill.message",msg);
    }

消費者代碼

從隊列中獲取用戶id和商品信息。然后,判斷該商品是否還有庫存,是否已經(jīng)秒殺過,如果都沒有,則進行訂單生產(chǎn)業(yè)務。

@RabbitListener(queues = "seckillQueue")
    public void receive(String msg) {
        MqMessage message = JSONObject.parseObject(msg, MqMessage.class);
        Long userid = message.getUserid();
        GoodsVo goods = message.getGoodsVo();
        //判斷是否還有庫存
        int stock = goods.getStockCount();
        if(stock <= 0) {
            return;
        }
        //判斷是否已經(jīng)秒殺到了
        Orders order = ordersService.getOne(new QueryWrapper<Orders>()
                .lambda().eq(Orders::getUserId,userid)
                .eq(Orders::getGoodsId, goods.getId()));
        if(order != null) {
            return;
        }
        ordersService.seckill(userid,goods);
    }

訂單模塊

訂單模塊:將用戶購買的商品的數(shù)量減少1,然后生成訂單和秒殺訂單。三者都成功后,在redis中存儲用戶id和訂單id,作為秒殺成功的記錄,如果用戶再次進行秒殺時,直接從redis查詢是否存在秒殺成功的記錄,存在即返回已經(jīng)秒殺,不存在就下一步。文章來源地址http://www.zghlxwxcb.cn/news/detail-788208.html

public void seckill(Long userid, GoodsVo goods) {
        Seckill seckill = seckillMapper.selectOne(
                new QueryWrapper<Seckill>().lambda().eq(Seckill::getGoodsId,goods.getId()));
        seckill.setStockCount(seckill.getStockCount()-1);
        seckillMapper.updateById(seckill);
        //生成訂單
        Orders orders = new Orders();
        orders.setUserId(userid).setGoodsId(goods.getId())
                .setGoodsCount(1).setStatu(0).setCreateDate(new Date())
                .setGoodsPrice(seckill.getSeckillPrice());
        baseMapper.insert(orders);
        //生成秒殺訂單
        SeckillOrders seckillOrders = new SeckillOrders();
        seckillOrders.setOrderId(orders.getId());
        seckillOrders.setUserId(userid);
        seckillOrders.setGoodId(goods.getId());
        int i=seckillOrdersMapper.insert(seckillOrders);
        redisUtil.set("order:"+userid+goods.getId(),i);

    }

到了這里,關于SpringBoot+RabbitMQ+Redis實現(xiàn)秒殺功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • SpringBoot RabbitMQ 實現(xiàn)消息隊列功能

    作者:禪與計算機程序設計藝術 在企業(yè)級應用中,為了提升系統(tǒng)性能、降低響應延遲、改善用戶體驗、增加系統(tǒng)的穩(wěn)定性、提高資源利用率等方面所需的功能之一就是使用消息隊列。RabbitMQ是一個開源的AMQP(Advanced Message Queuing Protocol)的實現(xiàn)消息隊列,它是用Erlang語言開發(fā)的。

    2024年02月09日
    瀏覽(24)
  • SpringBoot2+Vue2實戰(zhàn)(十四)springboot集成redis實現(xiàn)緩存

    添加redis緩存之后就不會一直刷新數(shù)據(jù)庫,減少數(shù)據(jù)庫壓力 pom.xml依賴 也可以自定義key,要用 \\\' \\\' 括起來 fileController 數(shù)據(jù)庫執(zhí)行刪除之后,第一次緩存也刪除,后面就不會請求數(shù)據(jù)庫 pom.xml application.yml EchartController 操作完數(shù)據(jù)庫更新緩存操作:(增刪改時使用) 第一種方法:

    2024年02月13日
    瀏覽(14)
  • Springboot集成Druid實現(xiàn)監(jiān)控功能

    Springboot集成Druid實現(xiàn)監(jiān)控功能

    Druid是阿里巴巴開發(fā)的號稱為監(jiān)控而生的數(shù)據(jù)庫連接池,在功能、性能、擴展性方面,都超過其他數(shù)據(jù)庫連接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource等等等,秒殺一切。Druid可以很好的監(jiān)控DB池連接和SQL的執(zhí)行情況,天生就是針對監(jiān)控而生的DB連接池。 官方的參考 http

    2024年04月12日
    瀏覽(30)
  • Springboot 如何自動上傳秒殺商品數(shù)據(jù)到Redis中上架商品

    Springboot 如何自動上傳秒殺商品數(shù)據(jù)到Redis中上架商品

    如下圖秒殺活動: 在這個秒殺活動中,需要自動上架一定時間段的商品,我們?nèi)绾螌崿F(xiàn)自動上傳呢? 我們可以通過定時任務來實現(xiàn)的。在秒殺活動開始前,需要將商品信息存儲到數(shù)據(jù)庫中,并設置好庫存和價格等信息。然后,可以通過定時任務的方式,每天定時從數(shù)據(jù)庫中

    2024年02月11日
    瀏覽(18)
  • SpringBoot集成WebSocket實現(xiàn)及時通訊聊天功能!!!

    SpringBoot集成WebSocket實現(xiàn)及時通訊聊天功能!!!

    注意: ? 至此,后端代碼就集成完了,集成完之后,記得重啟你的Springboot項目 前端Vue 1:新建Vue 頁面 ?路由: 代碼:路由根據(jù)你項目的實際情況寫 在用戶登錄的時候,需要將你的用戶名存儲到本地Session 中 ?效果圖: ?用戶甲: ? 用戶乙: ? 注:網(wǎng)上學習來源 SpringBoot集

    2024年02月01日
    瀏覽(23)
  • springboot集成elasticsearch,實現(xiàn)搜索提示補全功能

    springboot集成elasticsearch,實現(xiàn)搜索提示補全功能

    注:在此之前需要下載elasticsearch以及拼音分詞器??梢圆榭催@篇文章,免費下載,下載完直接解壓就行。 https://download.csdn.net/download/weixin_47874230/86514890 spring-data-elasticsearch版本需要與springboot版本對應,此處使用springboot版本為2.2.13.RELEASE

    2024年02月09日
    瀏覽(24)
  • Springboot + Websocket的集成實現(xiàn)簡單的聊天室功能

    Springboot + Websocket的集成實現(xiàn)簡單的聊天室功能

    WebSocket是一種網(wǎng)絡通信協(xié)議,它可以在單個TCP連接上實現(xiàn)雙向(全雙工)通信。WebSocket使用HTML5標準,并且可以在客戶端和服務器之間建立持久連接,這意味著連接在瀏覽器刷新或關閉后仍然保持打開狀態(tài)。 WebSocket的主要優(yōu)點包括: 1. 雙向通信:WebSocket支持客戶端和服務器之

    2024年03月21日
    瀏覽(27)
  • SpringBoot集成百度人臉識別實現(xiàn)登陸注冊功能Demo(二)

    SpringBoot集成百度人臉識別實現(xiàn)登陸注冊功能Demo(二)

    前言 上一篇SpringBoot集成百度人臉demo中我使用的是調用本機攝像頭完成人臉注冊,本次demo根據(jù)業(yè)務需求的不同我采用文件上傳的方式實現(xiàn)人臉注冊。 效果演示 首頁 注冊 后端響應數(shù)據(jù): 登錄 后端響應數(shù)據(jù): 項目結構 后端代碼實現(xiàn) 1、BaiduAiUtils工具類封裝

    2024年02月14日
    瀏覽(25)
  • SpringBoot實戰(zhàn)項目整合RabbitMQ+ElaticSearch實現(xiàn)SKU上下架功能

    SpringBoot實戰(zhàn)項目整合RabbitMQ+ElaticSearch實現(xiàn)SKU上下架功能

    ?? @ 作者: Eric ?? @ 主頁: https://blog.csdn.net/weixin_47316183?type=blog ?? @ 主題: SpringBoot實戰(zhàn)項目整合RabbitMQ+ElaticSearch實現(xiàn)SKU上下架功能 ?? @ 創(chuàng)作時間: 2023年07月03日 最終實現(xiàn)效果:針對SKU的上下架 上架效果: 1、后臺選擇 SKU ,點擊上架,該 SKU 修改為 上架 狀態(tài) 2、同時向

    2024年02月11日
    瀏覽(22)
  • 使用PHP和Redis實現(xiàn)簡單秒殺功能

    安裝Redis 首先,需要在服務器上安裝Redis。如果使用Linux系統(tǒng),可以使用命令行安裝。如果使用Windows系統(tǒng),可以下載并安裝Redis二進制文件。 創(chuàng)建Redis連接 在PHP中,可以使用Redis擴展來連接Redis服務器。需要在PHP文件中包含Redis擴展,并創(chuàng)建一個Redis連接對象。 創(chuàng)建秒殺商品 在

    2024年02月14日
    瀏覽(15)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包