Discuz 7.0 7.1 7.2 以及 X2 做了读写分离后出现搜索不存在的解决办法
为了提高负载能力,获得更好的反应速度,Discuz 7.0 7.1 7.2 以及 X2 版本里面内置了读写分离功能。
经过大量客户的使用反应来看,确实可以解决单台 MYSQL 高负载的问题。
但是有些客户反应在搜索的时候会频繁遇到“搜索不存在”的报错。在这里,我们分析下这个问题的由来和解决办法。
1,搜索原理。
论坛搜索的时候,会先对 threads 表的 subject 字段进行 like 搜索,由于 like 搜索消耗资源比较大,为了避免重复搜索,论坛会把搜索出来的数据进行缓存,写入到 searchindex 表里面去,当一定时间内再次搜索这个词的时候,就会直接读取 searchindex 里面的缓存数据。每天半夜12点,论坛的计划任务会把 searchindex 表的数据进行清空,以防这个表的体积越来越大。
2,读写分离原理。
读写分离是利用了 MYSQL 的主从复制功能。MYSQL 的主从复制是 主库打开二进制日志,主库会把所有的修改操作记录下来,然后传输到从库。从库把二进制日志接收后执行里面的 SQL 语句,从而把主库所做的修改在从库也做一次,保证主库和从库的数据是一样的。获得了两个数据同步的数据库。
有了两个数据能同步的数据库后,那么就可以把一些读取操作分流或者直接改为读取从库去了(从库不能进行写操作,不然数据会错乱),主库的压力就会大大减轻。
3,问题所在。
那为什么做了读写分离后,容易出现搜索不存在的错误呢?
因为做了主从复制后,两个数据库的同步不是实时进行的,在空闲的时候,可以保证两个数据库在1秒内同步完毕。但是在稍有压力的情况下,也许两个数据库会有超过1秒的延迟。
这个时候,当论坛的 like 搜索完成,写入了 searchindex 表后,会马上就跳转到读取 searchindex 数据的页面。这个时候 searchindex 表的数据还不一定已经100%同步到从库去。从库没有这个搜索数据的时候,搜索页面就报错了。
4,解决办法。
我们知道了问题所在后,那么就得想办法解决这个问题。既然主从复制容易受干扰,那么从主从复制上解决这个问题难度比较大。得从论坛程序下手。 既然是因为读从库的时候,从库还没有这个数据,那么主库是肯定有的了,如果我们在搜索完成的时候是读取主库的,那么就不会出现搜索不存在的错误了。
7.0 7.1 7.2的解决办法:
打开search.php文件,搜索$index = $sdb->fetch_first
把$index = $sdb->fetch_first改为$index = $db->fetch_first
那么就把读取 searchindex 数据的操作取消到从库读取了。只到主库。
X2的解决办法:
X2在设计读写分离功能的时候,就已经考虑到了主从同步有延迟的问题,预留了指定某些表不到从库去读取的功能。
打开配置文件config/config_global.php , 把$_config[‘db’][‘common’][‘slave_except_table’] = ”;的值设置成 common_searchindex
比如这样:$_config[‘db’][‘common’][‘slave_except_table’] = ‘common_searchindex’;