秒杀百万并发散发型思考方案
秒杀百万并发散发型思考方案
此方案是引用今日头条的一个大牛的方案,不是我想的,我只是熟悉一下制作流程
- 最可爱的c端限制方法,每一个进来的直接标识一个随机数,1-100随机一个数,11就让执行下面的流程。这样直接100w编程1w并发,开枪3秒后直接全部不成功。感觉如果这个放在pc端最好加密一下,移动端可能还好点。
- Nginx的反向代理层,用以上相同的思路进行。检测某个请求参数,存1/10的通过率,其他返回已抢完。这样并发进入服务器只有1000。
①找了很久的资料因为不是专门做这个nginx的没有太多的头绪,网上的资料不是很准确,因为自身能力无法正确锁定搜索词,后来想了想可以这样实现。首先找怎么搞随机数,然后判断是否是11,写一个if,最后输出给路径
②开始我们执行api赋值,因为随机数及时生成也需要验证。那么开始
#BEGIN
location /api/ceshi/index
{
set $args "a=1&b=2";
proxy_pass http://xx.xxxxx.com/api/ceshi/index;
}
#END
测试输出api 444 502 失败,不太明白哪里错了,再次测试 直接跳转不加参数
location /ceshiaa
{
set $args "a=1&b=2";
proxy_pass http://xx.xxxxx.com/api/ceshi/ceshi;
}
猜测可能是我的php文件中的接入写错了,测试直接使用$this->request()输出测试(我用的是tp6)
多次测试结果,不是tp的写法问题,是api/ceshi/index的问题可能是写法不对,再次测试,对了这个走的路径是GET方式
测试过程中几次中断,刚才还好改了几下就不行了,结论,最好重载nginx配置,可能缓存问题导致的。
测试发现这个location是不能写和下面接口一样的,eee,好吧孤陋寡闻了。
那么修改为ceshixx可以实现,那个http://这个网址是否可以换成别的我在想办法把,我用的bt面板,所以可以在网站哪里,直接修改配置文件,xx.xxxxx记得换成你们自己的
#BEGIN
location =/ceshixx
{
set $args "a=1&b=2";
proxy_pass http://xx.xxxxx.com/ceshi/ceshi/ceshi;
}
#END
输出正常,如果测试几个总不出来,可能是nginx缓存问题,重载配置,等一下应该就好了。
那么下面我开始写随机数和判断。
找了很多网上的资料有一个是安装插件然后去随机生成的需要set好几下,我就去搜了一下他的那个压缩包的名字,也没有什么好看的资料,后来我翻了一下bt中的server中的nginx,看到了lua这个几个字,nginx好像是可以调用lua的那么测试了一下这个
成功输出随机数,那么一个问题,这样调用在高并发的情景下,合适吗?查询了一些资料都在解释,高并发状态nginx调用lua是可以解决部分场景的就是说应该可以这样用。累死。。
下面综合执行
上面只是输出了一个随机数,但是要调用判断,还是不会,经过找了几个小时资料终于执行成功
这个也有点问题,就是不支持中文好像,只能写个bushi
那么下面开始组合使用
还是500说明这样行,在block执行nginx的写法是不行的,再去找找
If 这东西记得放一个空格 我草
经过查找资料终于实现部分功能我草,据说这样使用set_by_lua的方式是不太好的,如果以后使用请找服务器端给你写个lua然后用content_by_lua_block的方式给你引进来吧
下面再次开始执行跳转,这里成功了,也出现了几个问题,proxy_pass不能出现在if里面,charset如果不设置,输出text/html就乱码了,但是json没事
#BEGIN
location =/ceshixx
{
#设置content type
default_type application/json;
#charset utf-8;
set_by_lua $rd '
local a = math.random(10)
return a;
';
if ($rd != '1') {
return 201 '{"status":"success","result":"已经卖完了","code":"201"}';
}
set $args "a=1&b=2";
proxy_pass http://xx.xxxxx.com/ceshi/ceshi/ceshi;
}
#END
- 程序入口来一个布隆过滤器
解释一下布隆过滤器,
①使用hash的方式进行判定输入的是否已经存在(输入过)
public function index(){
dump($this->JSHash("ceshi1"));
dump($this->ELFHash("ceshi1"));
dump($this->FNVHash("ceshi1"));
}
/**
* 由Justin Sobel编写的按位散列函数
*/
public function JSHash($string, $len = null)
{
$hash = 1315423911;
$len || $len = strlen($string);
for ($i=0; $i<$len; $i++) {
$hash ^= (($hash << 5) + ord($string[$i]) + ($hash >> 2));
}
// var_dump(($hash % 0xFFFFFFFF) & 0xFFFFFFFF);die;
return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;
}
/**
* 类似于PJW Hash功能,但针对32位处理器进行了调整。它是基于UNIX的系统上的widley使用哈希函数。
*/
public function ELFHash($string, $len = null)
{
$hash = 0;
$len || $len = strlen($string);
for ($i=0; $i<$len; $i++) {
$hash = ($hash << 4) + ord($string[$i]); $x = $hash & 0xF0000000; if ($x != 0) { $hash ^= ($x >> 24);
}
$hash &= ~$x;
}
// var_dump(($hash % 0xFFFFFFFF) & 0xFFFFFFFF);die;
return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;
}
/**
* 参考 http://www.isthe.com/chongo/tech/comp/fnv/
*/
public function FNVHash($string, $len = null)
{
$prime = 16777619; //32位的prime 2^24 + 2^8 + 0x93 = 16777619
$hash = 2166136261; //32位的offset
$len || $len = strlen($string);
for ($i=0; $i<$len; $i++) {
$hash = (int) ($hash * $prime) % 0xFFFFFFFF;
$hash ^= ord($string[$i]);
}
// var_dump(($hash % 0xFFFFFFFF) & 0xFFFFFFFF);die;
return ($hash % 0xFFFFFFFF) & 0xFFFFFFFF;
}
②这三个选一个使用
看了很多网上的描述其实,布隆过滤简单来说就是用hash的方式把传入的一种规定的格式转换成int的不重复整数串。
其实这个实现方式到了这里已经很简单了,其实好多应用其实已经应该是封装好的了。
https://learnku.com/articles/35803
用这个吧挺好用的 判断和事务都有了
要不就搜索布隆过滤器php等关键词基本都一样,这个看的还好。
③set的删除还是比较麻烦的嵌入塞进去,也挺麻烦。然后直接设置shell过一个条件,然后执行删除相应的库得了,这个里面可以选一个特用的库,记得别删错了。Select()一定记得要不删了常用的 不笑了吗?
这个是三重选择,就是直接全部判断三种是否都没有 那么就是没有了,其实到这里的需求已经很小了。
- 库存为零,程序入口拦截请求。
在程序初始的地方进行判断一个此次活动的redis标识是否存在,如果存在返回已经抢完,如果没有执行下面的程序。
- 如果客户没有购买,那么可以在执行前设置一个redis参数 购买个数 如果少一个就用decr 多一个就用incr,4和5可以并起来。
- 数据在确认订单的时候就需要插入数据库了,如果redis爆了,兹,返回抢完把,要不就集群,1000并发单机基本可以了,前端页面的秒杀多几项确认,就可以顺带拉开sql的执行。
浙公网安备 33010602011771号