PHP服务器性能问题 | 利用Redis做缓存实现高并发——轻量级

每个系统都会生成新的数据,那么就有新的单据编号,而且单据编号要求唯一,编号可能是随机的,可能是递增的数字。如果是数字,那么在多用户同时访问的时候就会导致生成相同的编号,这时候利用Redis做一下缓存,设置表字段的唯一索引就可以实现小并发量的要求。

分析:用户发起请求,读取Redis的值(如果没有就从数据库中加载),在该值的基础上+1,先更新到Redis,再更新到MySQL数据库。因为Redis读写速度远远超越MySQL,利用Redis做缓冲性能得以大幅度提升,生成唯一单据号就可以得以保证。(严格来说,还是有可能出现重复的,避免逻辑错误,在单据编号上价格 UNIQUE INDEX 就得以解决)。

 

以下是 此类的代码:

程序使用的CI框架开发,主要逻辑在  get_prefix_new_number 方法

<?php
/**
 * Created by PhpStorm.
 * 区分类型(前缀)的自增的单据编号 生成器
 * User: Jolon
 * Date: 2018/12/27 0027 11:17
 */

class Prefix_number_model extends My_model{
    protected $table_name = 'prefix_number';

    private $_fixed_length = 6;// 固定长度(不足的左边补 0)

    public function __construct(){
        parent::__construct();

    }

    /**
     * 查询指定 前缀的 记录
     * @author Jolon
     * @param string $order_prefix  前缀名
     * @return mixed
     */
    public function get_prefix($order_prefix){
        $where = ['prefix' => $order_prefix];

        $this->purchase_db->where($where);
        $row = $this->purchase_db->get($this->table_name)->row();

        return $row;
    }

    /**
     * 拼接指定格式的 前缀
     * @param string $order_prefix  前缀名
     * @param int    $number        增量
     * @param int    $fixed_length  数值部分长度(不足的自动补0)
     * @return string
     */
    public function joinNumberStr($prefix, $number, $fixed_length){
        return $prefix.str_pad($number, !empty($fixed_length) ? $fixed_length : $this->_fixed_length, "0", STR_PAD_LEFT);// 编号不足长度 左边自动补0
    }

    /**
     * 生成 指定前缀的 最新编号(自动更新编号记录)
     * @author Jolon
     * @param string    $order_prefix   前缀
     * @param int       $add_number     增量(默认 1)
     * @param int       $fixed_length   编号长度(默认 6,用来填充)
     * @return bool|string
     */
    public function get_prefix_new_number($order_prefix,$add_number = 1,$fixed_length = 6){
        $operator_key    = strtoupper('get_prefix_new_number_'.$order_prefix);
        $existsKeyNumber = $this->rediss->getData($operator_key);// 命令用于获取指定 key 的值。如果 key 不存在,返回 nil 。如果key 储存的值不是字符串类型,返回一个错误

        if(empty($existsKeyNumber)){
            $result = $this->update_prefix($order_prefix,$add_number);// 自动更新或增加前缀的计数
            if(empty($result)){
                return false;
            }else{
                $row = $this->get_prefix($order_prefix);// 获取更新后的数据
                $number_int_value = $row->number;
                $number = $this->joinNumberStr($order_prefix,$number_int_value,$fixed_length);// 编号不足长度 左边自动补0

                $this->rediss->setData($operator_key,$number_int_value);// 只是存储数字
            }
        }else{
            $this->rediss->incrByData($operator_key,$add_number);// 命令将 key 中储存的数字加上指定的增量值
            $number_int_value = $this->rediss->getData($operator_key);
            $number = $this->joinNumberStr($order_prefix,$number_int_value,$fixed_length);// 编号不足长度 左边自动补0

            // 更新到数据库
            $this->purchase_db->set(['number' => $number_int_value, 'date' => date('Y-m-d')])
                ->where('prefix', $order_prefix)
                ->update($this->table_name);
        }

        return $number;
    }

    /**
     * 增加 指定前缀的 计数值(没有该前缀的记录则自动插入)
     * @author Jolon
     * @param string    $order_prefix   前缀
     * @param int       $add_number     增量(默认 1)
     * @return mixed
     */
    public function update_prefix($order_prefix,$add_number = 1){
        $row = $this->get_prefix($order_prefix);
        if(empty($row)){// 不存在记录则新增记录
            $result = $this->insert_prefix_record($order_prefix,$add_number);// 插入前缀记录
        }else{// 存在记录则获取之前的 编号再增加指定值
            $update_data = [
                'number' => $row->number + $add_number,
                'date'   => date('Y-m-d'),
            ];
            $this->purchase_db->set($update_data);
            $this->purchase_db->where('prefix', $order_prefix);
            $result = $this->purchase_db->update($this->table_name);

        }

        return $result;
    }

    /**
     * 插入指定前缀的记录
     * @author Jolon
     * @param string    $order_prefix   前缀名称
     * @param int       $begin_number   起始值(默认 1)
     * @param string    $note           备注
     * @return mixed
     */
    public function insert_prefix_record($order_prefix,$begin_number = 1,$note = ''){

        $insert_data = [
            'prefix' => $order_prefix,
            'number' => intval($begin_number),
            'date'   => date('Y-m-d'),
            'note'   => $note
        ];

        return $this->purchase_db->insert($this->table_name,$insert_data);
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值