admin 发布的文章

前因后果不扯了,我前几篇贴文都在说这个事,简单说就是上周系统大并发下炸了。
今天的流量比上周还大一倍,但数据库和服务器完全是在低负荷下运行。(数据库有的那个尖峰,是因为数据库缩容后比例尺变化显示原因,不是真的大负荷)
开心。

success.png
success1.png

程序在处理请求读取非实时数据时,通常会先从 Redis 缓存中获取数据。如果缓存失效或过期,程序会转而从数据库读取最新数据,然后将结果写回 Redis。听起来没问题,对吧?确实,这是标准的缓存更新流程,我最初也没觉得有什么不对。
但问题来了:在高并发场景下,事情就没那么简单了。假设缓存恰好失效,从缓存过期到新数据写入 Redis 的这段时间,哪怕只有几十毫秒就可能有无数个请求同时涌入。这些请求发现缓存没了,都会去查数据库、更新 Redis,轻则系统负荷升高,重则引起缓存混乱系统失效。我脑子不好使没转过弯,想不出啥好办法解决。后来一问ai,才发现,哎,这早就是个成熟的算法了,简单又巧妙,赶紧写下来备忘!

var dupMu sync.Mutex   //互斥锁,用来锁定缓存失效请求
func heavyLoadFunc() {
  err:=LoadFromRds(keyname, param, &list)  //读redis
  if err==nil && list!=nil {   //缓存命中直接返回数据
    ....
    return list
  }
  dupMu.Lock()     //双重缓存锁。缓存未命中,锁定,只允许一个个排队进入
  defer dupMu.Unlock()
  err:=LoadFromRds(keyname, param, &list)   //第二次读取redis。即,排队的未命中请求,第一个请求会缓存再次失败进入数据库更新redis数据,但在第一个完成后,其余请求即可从redis获得数据,防止再次更新。太巧妙和简单了。
  if err==nil && list!=nil {
    ....
    return list
  }
  list,err=getDataFromDb()  //从数据库更新
  return list  
}

你没猜错,我就是吃饱了撑的,折腾一下,练下手艺。
大道理当然也会讲嘛,mysql资源占用太大,博客这种东西,不用浪费资源,sqlite足也。(当然,我不会告诉你的是,我rs1000 8g的内存空余7g多,cpu占用是0.00)。
首先,需要导出当前mysql的sql文件,mysqldump人人都会,不用说了。但如果你问gpt的话,它会让你加上一些兼容的参数,一加,反而不行,中文乱码了,所以,用默认的参数导出即可。
然后下载sql语句转换工具,因为sqlite与mysql在sql层级有小小区别。 https://raw.githubusercontent.com/dumblob/mysql2sqlite/master/mysql2sqlite
转换sql文件为sqlite格式,再用sqlite3导入上述的sql文件即可。
将sqlite数据库文件放入php可以访问到的非web的目录(你总不希望别人直接下载你的数据库吧),重要的事情来了,一定要确保这个目录php进程有写权限。sqlite文件自然需要有写权限,但该目录也一定要有写权限,因为在同级目录sqlite会建临时的wal和shm文件。
最后,修改typecho的config.inc.php,将mysql改成sqlite:

$db = new Typecho_Db('Pdo_SQLite', 'typecho_');
$db->addServer(array (
  'file' => 'sqlite文件绝对路径',
), \Typecho\Db::READ | \Typecho\Db::WRITE);

如果php没有安装pdo_sqlite模块的话,也需要装一下。
在配置文件中加上define("__TYPECHO_DEBUG__",true); 可以看到详细的出错信息,如果你不幸出错了的话。

我已经说过几次这玩意烂了,结果没想到它比我想象中还烂。
为了良好的seo效果,重要的事我必须说三次,长亭雷池垃圾,长亭雷池垃圾,长亭雷池垃圾,千万别用。
以前提到这玩意恶心之一,很普通的功能社区版(免费)都是不能用的。
恶心之二,自我放大攻击。比如人家攻击者发一个100字节的请求包,他会回10K字节去告诉攻击者,你不允许访问。。。这iq绝对负数。
说回这次的事。
我爸生前一直在做一个网站,他走后,这网站的维护自然我接手了。这是个专业性比较强,资料性也比较强的网站,就挂在那里别人来看来查资料就好了,不需要更新也不需要什么维护,我自己也不大上去看。
里面有个留言本,时不时有垃圾客来发垃圾留言,发几条就算了,但一发就是几千条什么的,受不了,所以我决定加人机。简单的办法就是装个waf。
我其实比较喜欢用宝塔家的,没有什么明显的短板,不过他家的问题是不能和nginx并存,所以,部署至少要两台机器,为爱发电的公益网站实在没必要,想想还是用这雷池凑合吧。
结果,今天上网站一看,https证书过期一周了!但问题是,它不是号称自动续期吗?
赶紧手动续期,续不了,总是跳出错信息。倒腾半天后来发现了,它真够傻的,因为ssl续期,需要http挑战,而我的服务器是设置的http重定向到https。。。 它居然这个都没处理好,把http挑战当普通访问重定向到https了,let's不处理302,所以,挂了。
太不专业的垃圾了,马上要清明了,我烧香心里都有疙瘩了。

waf1.jpg