在資料庫處理中,Join操作是最基本且最重要的操作之一,它能將不同的表連接起來,實現對數據集的更深層次分析 ...
千萬級數據併發解決方案(理論+實戰)
場景
秒殺 高併發
新聞系統 超大數據量
一般的網站 寫入的少 讀取的次數多
模糊查詢
數據量少的時候可以用 like
數據量多的時候用 Elasticsearch搜索引擎 占用磁碟空間比較大
生成數據
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `article_tmp`;
CREATE TABLE `article_tmp` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`url` varchar(255) NOT NULL,
`descs` varchar(255) NOT NULL,
`author` varchar(255) NOT NULL,
`add_time` varchar(255) NOT NULL,
`from` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=201 DEFAULT CHARSET=utf8;
INSERT INTO `article_tmp` VALUES ('1', '模型驅動設計的構造塊(下)——DDD', 'https://www.cnblogs.com/afei-24/p/16985996.html', '3. 領域對象的生命周期 每個對象都有生命周期,如下圖所示。對象自創建後,可能會經歷各種不同的狀態,直至最終消亡——要麼存檔,要麼刪除。當然很多對象是簡單的臨時對象,僅通過調用構造函數來創建,用來做一些計算,然後由垃圾收集器回收。這類對象沒必要搞得那麼複雜。但有些對象具有更長的生命周期,其中一部分時 ...', 'Ruby_Lu', '2023-01-06 07:22', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('2', 'IT編程相關內容彙總 - 進階者系列 - 學習者系列文章', 'https://www.cnblogs.com/lzhdim/p/17028789.html', '筆者工作了十多年了,對於技術也有一定的經驗,但是IT編程技術的更新是挺快的,特別是各種框架,各種中間件啥的都涌現出來了。這篇博文筆者打算將IT編程的前端、後端、資料庫和移動端做一個博文知識彙總,讓閱讀筆者博客的讀者能夠有一個系統化學習編程技術的博文。前面已經有一個博文進行過相關的介紹,但是那個比較普 ...', 'lzhdim', '2023-01-06 00:00', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('3', '小白致力於成為前後端開發程式員', 'https://www.cnblogs.com/pocn/p/16857245.html', '小白有個煩惱,做前端項目的時候,遇到兩種情況一種是在vue框架下,使用HTML寫頁面,script部分代碼裡面的方法基本上使用JS來寫;一種同樣在vue框架下,通過安裝的框架來構建頁面,script中使用的方法也多是安裝的框架中封裝好的方法。小白是個倒霉催的孩子,負責的項目比較多,常常在兩種情況下切 ...', 'BOBO~', '2023-01-05 22:51', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('4', 'BST查找結構與折半查找方法的實現與實驗比較', 'https://www.cnblogs.com/Az1r/p/17028980.html', '簡介 作業:查找結構與排序方法 作業題目: BST 查找結構與折半查找方法的實現與實驗比較 要求編寫程式實現 BST 存儲結構的建立(插入)、刪除、查找和排序演算法; 實現折半查找演算法;比較 BST 查找與折半查找方法的時間性能。 作業要求: 1. 設計 BST 的左右鏈存儲結構,並實現 BST 插入 ...', '江水為竭', '2023-01-05 22:12', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('5', 'Java開發學習(五十)----MyBatisPlus快速開發之代碼生成器解析', 'https://www.cnblogs.com/xiaoyh/p/16468217.html', '1、代碼生成器原理分析 造句: 我們可以往空白內容進行填詞造句,比如: 在比如: 觀察我們之前寫的代碼,會發現其中也會有很多重覆內容,比如: 那我們就想,如果我想做一個Book模塊的開發,是不是只需要將紅色部分的內容全部更換成Book即可,如: 所以我們會發現,做任何模塊的開發,對於這段代碼,基本上 ...', '|舊市拾荒|', '2023-01-05 21:57', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('6', 'VMware搭建內網滲透環境', 'https://www.cnblogs.com/LeslieSec/p/17028722.html', '網路結構: 攻擊機:kali 192.168.1.103 DMZ區域:防火牆 WAN:192.168.1.104 LAN:192.168.10.10 winserver03 LAN:192.168.10.11 用戶辦公區域:路由器 WAN:192.168.10.20 LAN:192.168.20.1 ...', '林燼', '2023-01-05 21:21', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('7', '自動增長配置不合理導致的性能抖動', 'https://www.cnblogs.com/zhuancloud/p/17028870.html', '背景 客戶收到了SQL專家雲告警郵件,在凌晨2點到3點之間帶有資源等待的會話數暴增,請我們協助分析。 現象 登錄SQL專家雲,進入活動會話的趨勢分析頁面,下鑽到2點鐘一個小時內的數據,看到每分鐘的等待數都在100左右,2點15分時達到200。 轉到活動會話原始數據頁面,看到大量會話都在等待,等待類型 ...', '格瑞趨勢技術團隊', '2023-01-05 21:07', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('8', 'C | 指針', 'https://www.cnblogs.com/lijiuliang/p/17028849.html', '1.什麼是指針 指針是一種變數,也稱指針變數,它的值不是整數、浮點數和字元,而是記憶體地址。指針的值就是變數的地址,而變數有擁有一個具體值。因此,可以理解為變數直接引用了一個值,指針間接地引用了一個值。一個存放變數地址的類型稱為該變數的“指針”。 指針變數的大小? 以32位系統為例,每個位元組(即一個內 ...', '就良同學', '2023-01-05 20:54', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('9', '07.synchronized都問啥?', 'https://www.cnblogs.com/wyz1994/p/17028834.html', '大家好,我是王有志。關註王有志,一起聊技術,聊游戲,從北漂生活談到國際風雲。最近搞了個抽獎送書的活動,歡迎點擊鏈接參與。 如果Java面試有什麼是必問的,synchronized必定占據一席之地。初出茅廬時synchronized的用法,成長後synchronized的原理,可謂是Java工程師的“ ...', '王有志', '2023-01-05 20:48', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('10', 'JavaScript 中如何攔截全局 Fetch API 的請求和響應?', 'https://www.cnblogs.com/wenruo/p/17028832.html', '本文翻譯自 Intercepting JavaScript Fetch API requests and responses 攔截器是可用於預處理或後處理 HTTP 請求的代碼塊,有助於全局錯誤處理、身份驗證、日誌記錄等。在本文中,你將學習如何攔截 JavaScript Fetch API 請求。 ...', '我不吃餅干呀', '2023-01-05 20:47', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('11', '.gitignore文件配置以及gitee提交報Push rejected...錯誤解決', 'https://www.cnblogs.com/wren/p/17028830.html', '.gitignore文件配置 .gitignore 文件可以用來忽略被指定的文件或文件夾的改動。記錄在.gitignore文件里的文件或文件夾是不會被 git 跟蹤到,也就是被忽略的文件是不會被上傳到遠程倉庫的,如果文件已經存在於遠程倉庫中就無法通過.gitignore文件來忽略。 下麵總結了一些可 ...', '請叫我阿傑', '2023-01-05 20:46', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('12', 'Ventoy製作啟動盤和使用VMware測試啟動盤(論文版)', 'https://www.cnblogs.com/alittlemc/p/17027815.html', 'Ventoy是可用於製作啟動U盤的開源工具,在占用少量引導分區容量後,其他空間依舊可以正常當一般的U盤讀寫文件。它的最大特點是只要將iso、win、img、efi等之類的鏡像文件和引導文件移動到U盤中。比如導出微PE、杏雨梨雲的可啟動iso鏡像文件,移動到U盤中,在啟動時選擇微PE、杏雨梨雲任意一個... ...', 'alittlemc', '2023-01-05 20:45', 'https://www.cnblogs.com');
INSERT INTO `article_tmp` VALUES ('13', 'JUC併發編程詳解(通俗易懂)', 'https://www.cnblogs.com/ZhangHao-Study/p/16994667.html', '一、JUC簡介 在Java5.0提供了java.util.concurrent包,簡稱JUC,即Java併發編程工具包。JUC更好的支持高併發任務。 具體的有以下三個包: java.util.concurrent java.util.concurrent.atomic java.util.concu ...', '九八十', '2023-01-05 20:39', 'https://www.cnblogs.com');
在laravel中 創建
要提前配置好資料庫
//創建新的命令類
php artisan make:command Tests
//創建後使用命令
php artisan app:tests
在Tests文件中寫入
use DB;
public function handle()
{
echo Date('Y-m-d H-i-s')."\r\n";
$lists = DB::table('article_tmp')->get()->toArray();
for ($i = 0; $i < 10000000; $i++) {
$randindexArr = array_rand($lists,2);
$data['title'] = $data['descs'] = '';
foreach($randindexArr as $val){
$data['url']=$lists[$val]->url;
$data['cid']=rand(1,50);
$data['title'] .=mb_substr($lists[$val]->title,0,rand(2,16));
$data['descs'] .=mb_substr($lists[$val]->descs,rand(0,16),rand(32,64));
$data['author']=$lists[$val]->author;
$data['add_time']=$lists[$val]->add_time;
$data['from']=$lists[$val]->from;
}
DB::table('article')->insert($data);
};
echo Date('Y-m-d H-i-s')."\r\n";
}
運行命令 php artisan app:tests
生成數據
mysql查詢原則
數據多 併發高
欄位越多 體積越大
- 程式用到哪幾個欄位就查詢哪幾個欄位,儘量避免select * 查詢
- 一次用多少數據,就返回多少數據:加limit限制
- 儘量用 = ,and 不要用 >,< ,<>,or
- 欄位設計儘量 不為null
添加索引
- 針對熱點欄位添加索引
- 索引不一定是越多越好 因為會影響 insert,update,delete 的效率 (修改表數據的時候 ,mysql需要同步更新索引)
- 索引最好在開發的時候創建好,儘量避免在生產環境中創建索引(數據量大的時候,創建耗時較長,會影響業務)
一旦發生 掃表 效率是最低的
EXPLAIN 查看執行計劃
EXPLAIN SELECT * FROM article
WHERE author = "就良同學" and cid = 50;
最重要的兩個欄位 possible_keys key 如果為空 說明發生掃表
possible_keys 可能會用都到的索引
key 實際會用到的索引
rows 預估值
select_type (SIMPLE) 簡單查詢
id | select_type | possible_keys | key | rows |
---|---|---|---|---|
1 | SIMPLE | cid,author | author | 700 |
大數據量下進行的查詢 最好先查看執行計劃
EXPLAIN SELECT * FROM
article WHERE author = "就良同學" and cid = 50;
使用緩存
一個簡單使用本地文件來當緩存
public function index()
{
$data= '';
$cache_file = 'article_cid.txt';
if(!file_exists($cache_file)){
//創建文件
file_put_contents($cache_file,'');
}
//讀取數據
$data = file_get_contents($cache_file);
if($data){
$data= json_decode($data);
dump($data);
return ;
}
//沒有數據
$data=DB::table('article')->where('cid',21)->paginate(20);
file_put_contents($cache_file,json_encode($data));
dump($data);
}
緩存策略
旁路緩存策略
Cache-Aside
- 讀:
- 先到緩存裡面讀數據,如果讀到了就直接返回數據
- 如果讀不到數據,從資料庫中讀數據,然後存到 cache中
- 寫:
- 方案一. 更新完數據後 ,刪除緩存
- 方案一. 更新完數據後,不刪除緩存,直接更新它
缺陷1:首次請求 數據一定不在 cache裡面 ,需要到資料庫中查詢一下.
解決方方案 : 可以提前把數據放到 cache裡面 , '預熱數據'
缺陷2:對於寫操作比較頻繁的數據,直接造成緩存命中率較低。這時候緩存的意義就不大了。
解決方案:
- 要麼不緩存這種數據,要麼換緩存策略
- 資料庫數據和Cache中的數據不要求強一致:非同步更新DB和Cache,
- 資料庫數據和Cache中的數據必須強一致:
比如說 點贊量 瀏覽量 這些不是非常重要的數據,用非同步來處理
讀寫穿透策略
Read/Write-Through
- 讀:
- 從Cache讀數據,如果讀到數據就直接返回;如果讀不到數據的話,從資料庫中載入,然後寫入到Cache里
- 寫:
- 先查一下Cache,如果Cache中不存在的話,直接更新資料庫;如果Cache中存在,先更新Cache,然後Cache自己更新資料庫(相當於同步更新資料庫和Cache)
缺點:參考【Cache-Aside(旁路緩存策略)】
非同步緩存寫入策略
Write-Behind
- 寫:只操作Cache,不操作資料庫。什麼時候寫到資料庫?非同步寫入資料庫(可以寫一個命令行程式定時把Cache中的數據更新到資料庫)
應用場景:文章或商品的瀏覽量、點贊量、關註量等對數據的實時性要求不高的場景。
什麼樣的數據不適合放到Cache里?
- 體積太大的數據不適合。(1、消耗記憶體。2、網路負載比較高(web和redis不在同一臺機器上))
- 頻繁變動的數據,考慮一下是否需要放到緩存中
ab壓力測試
apachebench的縮寫
原理:ab程式會創建多個併發的訪問線程,模擬多個訪問者同時對某一個url進行訪問。所以,它可以測試的伺服器類型可以是apache,也可以是nginx、tomcat伺服器,也可以是IIS伺服器
註意:ab程式對發出負載的機器要求很低,也就是說它占用的cpu和記憶體非常低。但是因為它模擬大量的用戶請求,所以會給目標伺服器造成巨大的負載。比較類似CC攻擊。所以我們自己測試的時候,註意控制好請求量。
ab的安裝
- windows:apache的bin目錄里的ab.exe
- linux:apache的/usr/bin/ab
- 只想用ab工具,不想安裝Apache,怎麼辦?
1、伺服器是windows server:在開發機上,到apache的bin目錄下,拷貝ab.exe到伺服器上就行。
2、伺服器是centos:安裝httpd-tools,yum -y install httpd-tools
ab的版本:ab -V
ab程式的參數說明
-n在測試會話中所執行的請求個數。預設時,僅執行一個請求。
-c一次產生的請求個數。預設是一次一個。
-t測試所進行的最大秒數。其內部隱含值是-n 50000,它可以使對伺服器的測試限制在一個固定的總時間以內。預設時,沒有時間限制。
-p包含了需要POST的數據的文件。
-P對一個中轉代理提供BASIC認證信任。用戶名和密碼由一個:隔開,並以base64編碼形式發送。無論伺服器是否需要(即, 是否發送了401認證需求代碼),此字元串都會被髮送。
-T POST數據所使用的Content-type頭信息。
-v設置顯示信息的詳細程度-4或更大值會顯示頭信息,3或更大值可以顯示響應代碼(404,200等),2或更大值可以顯示警告和其他信息。
-V顯示版本號並退出。
-w以HTML表的格式輸出結果。預設時,它是白色背景的兩列寬度的一張表。
-i執行HEAD請求,而不是GET。
-x設置<table>屬性的字元串。
-X對請求使用代理伺服器。
-y設置<tr>屬性的字元串。
-z設置<td>屬性的字元串。
-C對請求附加一個Cookie:行。其典型形式是name=value的一個參數對,此參數可以重覆。
-H對請求附加額外的頭信息。此參數的典型形式是一個有效的頭信息行,其中包含了以冒號分隔的欄位和值的對(如,"Accept-Encoding:zip/zop;8bit")。
-A對伺服器提供BASIC認證信任。用戶名和密碼由一個:隔開,並以base64編碼形式發送。無論伺服器是否需要(即,是否發送了401認證需求代碼),此字元串都會被髮送。
-h顯示使用方法。
-d不顯示"percentage served within XX [ms] table"的消息(為以前的版本提供支持)。
-e產生一個以逗號分隔的(CSV)文件,其中包含了處理每個相應百分比的請求所需要(從1%到100%)的相應百分比的(以微妙為單位)時間。由於這種格式已經“二進位化”,所以比'gnuplot'格式更有用。
-g把所有測試結果寫入一個'gnuplot'或者TSV(以Tab分隔的)文件。此文件可以方便地導入到Gnuplot,IDL,Mathematica,Igor甚至Excel中。其中的第一行為標題。
-i執行HEAD請求,而不是GET。
-k啟用HTTP KeepAlive功能,即在一個HTTP會話中執行多個請求。預設時,不啟用KeepAlive功能。
-q如果處理的請求數大於150,ab每處理大約10%或者100個請求時,會在stderr輸出一個進度計數。此-q標記可以抑制這些信息。
ab測試結果
如:ab -c 10 -n 1000 http://lv.php.com/index/index
Concurrency Level: 10
模擬的客戶端的數量(10個客戶端)
Time taken for tests: 19.113 seconds
處理完1000個請求所話費的總時間
Complete requests: 1000
總共完成了多少個請求
Failed requests: 0
失敗的請求數
Total transferred: 896000 bytes
所有請求的響應數據長度的總長度,包含每個http請求的頭信息(header)和正文數據(body)
HTML transferred: 673000 bytes
所有請求數據的正文的長度
Requests per second: 52.32 [#/sec] (mean)
每秒鐘執行的請求數---吞吐率。值越大越好
(第一個)Time per request: 191.131 [ms] (mean)
客戶端平均每個請求的等待時間
(第二個)Time per request: 19.113 [ms] (mean, across all concurrent requests)
伺服器端平均每個請求的等待時間
Transfer rate: 45.78 [Kbytes/sec] received
數據傳輸速率。值越大越好
Connection Times (ms)
min mean[+/-sd] median max
(連接時間)Connect: 0 0 0.4 0 1
(處理時間)Processing: 98 189 103.5 179 1342
(等待時間)Waiting: 98 189 103.5 179 1342
(總時間 )Total: 98 190 103.5 179 1342
Percentage of the requests served within a certain time (ms)
50% 179
66% 182
75% 184
80% 186
90% 194
95% 200
98% 245
99% 284
100% 1342 (longest request)
完成本次測試的時間分佈,一般關註90%的處理時間
es擴展 (elasticsearch )
官網: https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
文檔:
https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/getting-started-php.html
軟體下載: https://elasticsearch.cn/download/
擴展安裝
composer require elasticsearch/elasticsearch
ElasticSearch重置密碼步驟(忘記密碼的情況)
1.停止Elasticsearch服務
2.編輯elasticsearch.yml文件,設置以下兩項為false;
xpack.security.enabled: false
xpack.security.transport.ssl.enabled: false
3.重啟es服務,刪除.security-7索引
curl -XDELETE -u elastic:changeme http://localhost:9200/.security-7
3.關閉ES服務設置以下兩項為true;
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
4.重啟es服務,進入es的bin目錄下
./elasticsearch-setup-passwords interactive
依次設置每個賬號密碼即可
獲取密碼:
進入es安裝目錄的bin文件中執行一下命令會返回最新的密碼
命令 : elasticsearch-reset-password -u elastic
預設用戶名: elastic
密碼: QhW4NJSQGzP13o2kVI6o
修改密碼的其他命令
https://devpress.csdn.net/cloud-native/65195642aae4e179c0b77cc4.html
開啟各種安全驗證後需要ssl證書才能正常登錄
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl:
enabled: true
keystore.path: certs/http.p12
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/transport.p12
truststore.path: certs/transport.p12
證書位置 config\certs\http_ca.crt
config/es.php
文件配置
return [
'host'=>['https://127.0.0.1:9200'],
'user'=>'elastic',
'pwd'=>'VX_IuVXQ6_WcfmBO8Mxc',
];
//初始化
use Elastic\Elasticsearch\ClientBuilder;
use Elastic\Elasticsearch\Exception\ClientResponseException;
use Elastic\Elasticsearch\Exception\ServerResponseException;
$client = ClientBuilder::create()
->setHosts(config('es.host'))
->setBasicAuthentication(config('es.user'), config('es.pwd'))
->setCABundle('cacrt/http_ca.crt')
->build();
分詞器要下載對應的版本
https://github.com/medcl/elasticsearch-analysis-ik
下載地址
https://github.com/medcl/elasticsearch-analysis-ik/releases
下載後解壓到 plugins/ik
目錄下麵 重啟 es即可
//創建映射
curl -XPOST http://localhost:9200/index/_mapping -H 'Content-Type:application/json' -d'
{
"properties": {
"content": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
}
}
}'
案例 增刪查改
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Elastic\Elasticsearch\ClientBuilder;
use Elastic\Elasticsearch\Exception\ClientResponseException;
use Elastic\Elasticsearch\Exception\ServerResponseException;
use Illuminate\Support\Facades\DB;
class MyesController extends Controller
{
protected $client;
public function __construct()
{
//初始化es
$this->client = $this->_init_es();
}
public function index()
{
// 創建索引
// $res = $this->_create_index();
// dd($res);
// $item = DB::table('article')->first();
// dd($item);
// $article_list = DB::table('article')->where('id', '<', 300)->get()->toArray();
// foreach ($article_list as $item) {
// $this->insert_update($item);
// }
//把數據寫入搜索引擎
// $res=$this->insert_update($item);
// dd($res);
//刪除文檔
// $this->del_doc();
//刪除索引
$this->del_index();
//全文搜索
// $res = $this->dosearch('C');
// echo "<pre>";
// print_r($res);
}
//初始化es
private function _init_es()
{
$es_config = [
'host' => ['https://127.0.0.1:9200'],
'user' => 'elastic',
'pwd' => 'QhW4NJSQGzP13o2kVI6o',
'cacrt' => base_path() . '\private\certs\http_ca.crt',
];
$client = ClientBuilder::create()
->setHosts($es_config['host'])
->setBasicAuthentication($es_config['user'], $es_config['pwd'])
->setCABundle($es_config['cacrt'])
->build();
return $client;
}
//創建索引
private function _create_index()
{
$params = [
'index' => 'article', //索引的名稱(相當於mysql中的表明)
'body' => [
'settings' => [
'number_of_shards' => 5, //設置數據的分片數,預設為5
'number_of_replicas' => 0, // 數據的備份數(如果只有一臺機器,設置為0)
],
'mappings' => [
'properties' => [
'id' => [
'type' => 'integer'
],
'cid' => [
'type' => 'integer'
],
'title' => [
'type' => 'text', // text類型,做模糊搜索用
"analyzer" => "ik_max_word", //較細粒度分詞,寫入數據用
"search_analyzer" => "ik_smart", // 較粗粒度分詞,查詢數據用
],
'descs' => [
'type' => 'text',
],
'author' => [
'type' => 'keyword', // keyword類型,做精確搜索用
],
],
],
],
];
$res = $this->client->indices()->create($params);
// 註意:索引不存在,就創建它。如果已存在,會報異常
return $res;
}
//寫入文檔數據(_doc 相當於 mysql表中的一條記錄)
private function insert_update($item)
{
$params = [
'index' => 'article',
'type' => '_doc',
'id' => $item->id,
'body' => [
'id' => $item->id,
'cid' => $item->cid,
'title' => $item->title,
'descs' => $item->descs,
'author' => $item->author,
]
];
$res = $this->client->index($params);
// 註意:該文檔不存在就創建一個,存在的話,就更新它
return $res;
}
//全文搜索
private function dosearch($keyword)
{
$eswhere = [];
$eswhere['bool']['must'][] = ['match' => ['title' => $keyword]];
$eswhere['bool']['must'][] = ['match' => ['descs' => $keyword]];
$esorder = ['id' => 'DESC'];
$where = [
// size和from組合可以用於分頁
'size' => 10, // 取10條數據
'from' => 0, // 從第幾條開始取
'index' => 'article', // 從哪個索引中查
'type' => '_doc',
'body' => [
'query' => $eswhere, //查詢條件
// 'sort' => $esorder, //排序條件 ,加上以後,_score 沒有值
//高亮顯示
'highlight' => [
'fields' => [
'title' => [
'pre_tags' => ['<span style="color:red">'],
'post_tags' => ['</span>']
],
'descs' => [
'pre_tags' => ['<span style="color:red">'],
'post_tags' => ['</span>']
],
],
],
]
];
$results = $this->client->search($where);
// $milliseconds = $results['took'];
// $maxScore = $results['hits']['max_score'];
// $score = $results['hits']['hits'][0]['_score'];
// $doc = $results['hits']['hits'][0]['_source'];
return $results->asArray();
}
//刪除文檔
private function del_doc()
{
for ($i = 1; $i < 1000; $i++) {
$this->client->delete(['index' => 'article', 'id' => $i]);
}
// 註意:如果該文檔已經刪除了,重覆刪除會報異常
exit('刪除完成');
}
//刪除索引
private function del_index()
{
$this->client->indices()->delete(['index' => 'article']);
// 註意:如果該索引已經刪除了,重覆刪除會報異常
}
}
es擴展 linux(centos7)中安裝
- centos7系統設置
註意:visualbox中,要先在“設置”中把網卡的連接方式改為“橋接網卡”(預設是網路地址轉換NAT模式)
1、網卡設置為“橋接模式”
2、cd /etc/sysconfig/network-scripts
3、vi ifcfg-enp0s3
修改兩個參數:
ONBOOT=no 改為:ONBOOT=yes
BOOTPROTO=dhcp 改為:BOOTPROTO=static
增加以下IP配置
IPADDR=192.168.31.34
NETMASK=255.255.255.0
GATEWAY=192.168.31.1
DNS1=114.114.114.114
保存退出後,重啟網路(service network restart)
驗證一下網路:ping www.baidu.com。如果能ping通,說明網路配置OK了
- 下載elasticsearch
如果centos7是純凈系統(minimal版本的)
1、安裝wget下載工具:yum -y install wget
2、進入一個目錄里,如:cd /home 註意:最好不要在系統目錄里下載文件
3、wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.16.1-linux-x86_64.tar.gz
- 安裝elasticsearch
註意:先把系統的防火牆關掉
service firewalld stop
1、解壓壓縮包
tar -xzvf elasticsearch-7.16.1-linux-x86_64.tar.gz
cd elasticsearch-7.16.1/config
2、修改配置文件
vi elasticsearch.yml
network.host:0.0.0.0
http.port:9200
node.name:node-1
cluster.initial_master_nodes:["node-1"]
3、cd /home/elasticsearch-7.16.1/bin
4、創建一個新的用戶
useradd es
5、切換到es帳號下
su es
6、啟動elasticsearch
./elasticsearch
==========================可能會報異常========================
一般需要設置一下centos的系統文件
vi /etc/security/limits.conf
直接在文件的最後增加以下幾行參數
* soft nofile 65536
* hard nofile 65536
* soft nproc 65536
* hard nproc 65536
保存後退出
vi /etc/sysctl.conf
直接在文件的最後增加下麵的參數
vm.max_map_count=655360
保存後退出
執行sysctl -p
然後再次到elasticsearch的bin目錄下執行./elasticsearch
在區域網(當前的windows電腦)的瀏覽器中輸入 192.168.31.34:9200,能訪問,說明安裝配置OK了
- 安裝ik分詞插件
1、進入到/home/elasticsearch-7.16.1/plugins目錄
2、創建一個目錄,如:mkdir ik
3、進入ik目錄中。cd ik
4、wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.16.1/elasticsearch-analysis-ik-7.16.1.zip --no-check-certificate
5、解壓
unzip elasticsearch-analysis-ik-7.16.1.zip
6、重啟elasticsearch
註意:不要在plugins目錄里留無關的目錄或文件
高併發/大數據量下,代碼編寫原則
- 儘量少用或不用join查詢,如果確實要用的話,註意時間開銷
- 儘量不在迴圈里操作資料庫
開啟OPCache緩存
修改 php.ini 文件 添加這部分內容
zend_extension=php_opcache
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=5
opcache.revalidate_freq=3
opcache.use_cwd=1
opcache.validate_timestamps=1
opcache.save_comments=1
opcache.enable_file_override=Off
opcache.fast_shutdown=1
opcache.mmap_base=0x20000000
查詢案例
不使用join查詢
// 關聯數據查詢
public function article_4(): array
{
//查詢 文章表 關聯欄位為 cid
$pages = DB::table('article')->orderBy('id', 'desc')->paginate(2000);
$list = $pages->items();
// 將所有的 cid 合併
foreach ($list as $item) {
$cidList[] = $item->cid;
}
// cid去重
$cidList = array_unique($cidList);
// 用whereIn 查出所需要的cid對應的 分類數據
$cate_list = $cate = DB::table('article_cate')->whereIn('id', $cidList)->get()->toArray();
$cates = [];
// 修改 cate_list 分類 索引為 數據的 id
foreach ($cate_list as $val) {
$cates[$val->id] = $val;
}
return compact('list', 'cates');
}
view視圖
<table class="layui-table">
<tr>
<th>id</th>
<th>文章分類</th>
<th>文章標題</th>
<th>添加時間</th>
</tr>
@foreach($list as $v)
<tr>
<td>{{$v->id}}</td>
<td>{{$cates[$v->cid]->title}}</td>
<td>{{$v->title}}</td>
<td>{{$v->add_time }}</td>
</tr>
@endforeach
</table>
給laravel DB操作添加擴展
php artisan make:provider DBServiceProvider
文件路徑在 app/provider
use Illuminate\Database\Query\Builder as QueryBuilder;
public function boot(): void
{
// 將數據的索引設置 $index
QueryBuilder::macro('abbbc', function ($index) {
// echo '擴展的方法';
$res = $this->get()->toArray();
$result = [];
foreach($res as $val){
$result[$val->$index] = $val;
}
return $result;
});
}
註冊到 config\app
裡面
'providers' => ServiceProvider::defaultProviders()->merge([
// ...
App\Providers\DBServiceProvider::class,
])->toArray(),
使用示例
$cates=DB::table('article_cate')->abbbc('id');
// 將數據的索引設置為 id ;