Redis realiza a função de pico

Na vida real, a função de pico é mais comum, como 12306 obtenção de ingressos, atividades de pico do sistema de comércio eletrônico etc. O chamado pico, da perspectiva do negócio de aplicativos, significa que vários usuários "competem" por um determinado recurso em um curto período de tempo. O recurso aqui é uma commodity na maioria dos cenários de pico; do ponto de vista técnico, é uma combinação de vários threads. Recursos para operar. Portanto, para realizar a função spike, é necessário controlar a competição do segmento por recursos, não apenas para garantir alta eficiência e simultaneidade, mas também para garantir a correção da operação e atender às reais necessidades do negócio.

As ideias de otimização para pico são:

  • Escreva na memória.
  • Realize o processamento assíncrono multithread.
  • Realize o processamento distribuído.

[Exemplo] Um exemplo de uso de multi-threading para atingir 1000 pessoas matando 100 telefones celulares em segundos.

(1) No arquivo de informações de configuração pom.xml, adicione as dependências do iniciador Redis e do cliente Jedis:

<!-- Redis启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.4.0</version>
</dependency>

<!-- Jedis客户端依赖 -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.3.0</version>
</dependency>

(2) Implementação de SecondKill (SecondKill.java): Crie vários threads e use a função de transação do Redis para realizar a segunda função de eliminação.

package com.pjb.seckill;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
import java.util.List;

/**
 * 秒杀抢购
 * @author pan_junbiao
 **/
public class SecondKill implements Runnable
{
    String key = "iphone";
    Jedis jedis = new Jedis("127.0.0.1",6379);
    String userInfo;

    public SecondKill(String userInfo)
    {
        this.userInfo = userInfo;
    }

    @Override
    public void run()
    {
        try
        {
            jedis.watch(key); //watchkeys

            String val = jedis.get(key);
            int valint = Integer.valueOf(val);

            if(valint<=100 && valint>=1)
            {
                //1、使用MULTI命令开启事务
                Transaction tx = jedis.multi();

                //2、事务命令入队
                tx.incrBy(key,-1);

                //3、使用EXEC命令执行事务
                //提交事务。如果此时watchkeys被改动了,则返回null
                List<Object> list = tx.exec();

                if(list==null || list.size()==0)
                {
                    String failuserinfo = "fail_" + userInfo;
                    String failinfo = "用户:" + failuserinfo + "商品争抢失败,抢购失败";
                    System.out.println(failinfo);
                    //抢购失败业务逻辑
                    jedis.setnx(failuserinfo,failinfo);
                }
                else
                {
                    for(Object succ : list)
                    {
                        String succuserinfo = "succ_" + succ.toString() + "_" + userInfo;
                        String succinfo = "用户:" + succuserinfo + " 抢购成功,当前抢购成功人数:" + (1 -(valint -100));
                        System.out.println(succinfo);
                        //抢购成功业务逻辑
                        jedis.setnx(succuserinfo,succinfo);
                    }
                }
            }
            else
            {
                String failuserinfo = "kcfail_" + userInfo;
                String failinfo1 = "用户:" + failuserinfo + " 商品被抢购完毕,抢购失败";
                System.out.println(failinfo1);
                jedis.setnx(failuserinfo,failinfo1);
                return;
            }
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            jedis.close();
        }
    }
}

(3) O programa principal (SecondKillTest.java): o programa de entrada da função spike, usado para criar um pool de threads, ao mesmo tempo, gerar um ID de usuário, chamar o código da função spike e concluir a tarefa spike.

package com.pjb.seckill;

import com.pjb.util.RedisHelper;
import redis.clients.jedis.Jedis;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Redis秒杀功能的实现,1000人抢购100部手机
 * @author pan_junbiao
 **/
public class SecondKillTest
{
    public static void main(String[] args)
    {
        final String key = "iphone";
        //20个线程池并发数
        ExecutorService executor = Executors.newFixedThreadPool(20);

        final Jedis jedis = new Jedis("127.0.0.1",6379);
        jedis.del(key); //先删除
        jedis.set(key,"100"); //设置起始的抢购数
        jedis.close();

        for(int i=0; i<1000; i++)
        {
            String userInfo = "pan_junbiao的博客" + i;
            executor.execute(new SecondKill(userInfo));
        }
        executor.shutdown();
    }
}

Resultados de:

 

Acho que você gosta

Origin blog.csdn.net/pan_junbiao/article/details/111478937
Recomendado
Clasificación