Seckill system - optimization of high concurrency

The seckill system faces the following problems:
( 1 ) The cdn cache cannot be used because the system logic cannot be placed in the cdn.
( 2 ) Difficulty in back-end caching: inventory problem, because mysql transaction operation (set joint primary key) is used.
( 3 ) One row of data competition: hot commodity, because multiple users operate on a certain piece of data in the database at the same time.
The optimization scheme of the seckill system:
( 1 ) Front-end control: Expose interface, button to prevent repeated submission.
( 2 ) Separation of dynamic and static data: cdn cache, back-end Redis cache.
( 3 ) Transaction competition optimization: reduce the transaction lock time, put the client logic on the mysql server, and avoid the influence of network delay and GC. GC (Garbage Collection) garbage collection mechanism
Use Redis to optimize the address exposure interface, create a new cache package under the dao package, then create a RedisDao.java function, and configure the redisdao constructor in spring - dao.xml.
RedisDao.java:
public class RedisDao {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final JedisPool jedisPool;
    public RedisDao(String ip, int port) {
        jedisPool = new JedisPool(ip, port);
    }
private RuntimeSchema<Seckill> schema = RuntimeSchema.createFrom(Seckill.class);
    public Seckill getSeckill(long seckillId) {
        try {
            Jedis jedis = jedisPool.getResource();
            try {
                String key = "seckill:" + seckillId;
                byte[] bytes = jedis.get(key.getBytes());
                if (bytes != null) {
                    Seckill seckill = schema.newMessage();
                    ProtostuffIOUtil.mergeFrom(bytes, seckill, schema);
                    return seckill;
                }
            } finally {
                jedis.close();
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }
    public String putSeckill(Seckill seckill) {
        try {
            Jedis jedis = jedisPool.getResource();
            try {
                String key = "seckill:" + seckill.getSeckillId();
                byte[] bytes = ProtostuffIOUtil.toByteArray(seckill, schema,
                    LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
                int timeout = 60 * 60; 
                String result = jedis.setex(key.getBytes(), timeout, bytes);
                return result;
            } finally {
                jedis.close();
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }
}
For the concurrency problems caused by network delay and GC, use the stored procedure to complete the entire transaction on the mysql side. The second-kill stored procedure is implemented as follows.
DELIMITER $$
CREATE PROCEDURE `seckill`.`execute_seckill`
  (in v_seckill_id bigint,in v_phone bigint,
    in v_kill_time timestamp,out r_result int)
  BEGIN
    DECLARE insert_count int DEFAULT 0;
    START TRANSACTION;
    insert ignore into success_killed
      (seckill_id,user_phone,create_time)
      values (v_seckill_id,v_phone,v_kill_time);
    select row_count() into insert_count;
    IF (insert_count = 0) THEN
      ROLLBACK;
      set r_result = -1;
    ELSEIF(insert_count < 0) THEN
      ROLLBACK;
      SET R_RESULT = -2;
    ELSE
      update seckill
      set number = number-1
      where seckill_id = v_seckill_id
        and end_time > v_kill_time
        and start_time < v_kill_time
        and number > 0;
      select row_count() into insert_count;
      IF (insert_count = 0) THEN
        ROLLBACK;
        set r_result = 0;
      ELSEIF (insert_count < 0) THEN
        ROLLBACK;
        set r_result = -2;
      ELSE
        COMMIT;
        set r_result = 1;
      END IF;
    END IF;
  END;
$$
DELIMITER ;
Finally, create a function to store and execute the seckill operation in ServiceService.java, implement this interface in SeckillDao.java, use mybatis to call the stored procedure in SeckillDao.xml, and complete the configuration in SeckillServiceImpl.java on the server side.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325179894&siteId=291194637