6月11号
EPOLL
首先我們要知道我們為什么要選擇EPOLL模型
select,需要遍歷socket列表,頻繁的對等待隊列進行添加移除操作,
數據到達后還需要給變量所有socket才能獲知哪些socket有數據
兩個操作消耗的時間隨著要監控的socket的數量增加而大大增加,
處于效率考慮才規定了最大只能監視1024個socket
多線程會遇到資源瓶頸,什么才是解決高并發最有效的方式呢
linux中提供了epoll 這種多路復用的IO模型,注意其他平臺沒有相應的實現
所以epoll僅在linux中可用
而
epol為了解決這個問題,在內核中維護了一個就緒列表,
1.創建epoll對象,epoll也會對應一個文件,由文件系統管理
2.執行register時,將epoll對象 添加到socket的等待隊列中
3.數據到達后,CPU執行中斷程序,將數據copy給socket
4.在epoll中,中斷程序接下來會執行epoll對象中的回調函數,傳入就緒的socket對象
5.將socket,添加到就緒列表中
6.喚醒epoll等待隊列中的進程,
進程喚醒后,由于存在就緒列表,所以不需要再遍歷socket了,直接處理就緒列表即可
解決了這兩個問題后,并發量得到大幅度提升,最大可同時維護上萬級別的socket
#coding:utf-8
#客戶端
#創建客戶端socket對象
import socket
clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#服務端IP地址和端口號元組
server_address = ('127.0.0.1',1688)
#客戶端連接指定的IP地址和端口號
clientsocket.connect(server_address)
while True:
#輸入數據
data = raw_input('please input:')
if data == "q":
break
if not data:
continue
#客戶端發送數據
clientsocket.send(data.encode("utf-8"))
#客戶端接收數據
server_data = clientsocket.recv(1024)
print ('客戶端收到的數據:',server_data)
#關閉客戶端socket
clientsocket.close()
# coding:utf-8
import socket, select
server = socket.socket()
server.bind(("127.0.0.1", 1688))
server.listen(5)
msgs = []
fd_socket = {server.fileno(): server}
epoll = select.epoll()
# 注冊服務器的 寫就緒
epoll.register(server.fileno(), select.EPOLLIN)
while True:
for fd, event in epoll.poll():
sock = fd_socket[fd]
print(fd, event)
# 返回的是文件描述符 需要獲取對應socket
if sock == server: # 如果是服務器 就接受請求
client, addr = server.accept()
# 注冊客戶端寫就緒
epoll.register(client.fileno(), select.EPOLLIN)
# 添加對應關系
fd_socket[client.fileno()] = client
# 讀就緒
elif event == select.EPOLLIN:
data = sock.recv(2018)
if not data:
# 注銷事件
epoll.unregister(fd)
# 關閉socket
sock.close()
# 刪除socket對應關系
del fd_socket[fd]
print(" somebody fuck out...")
continue
print(data.decode("utf-8"))
# 讀完數據 需要把數據發回去所以接下來更改為寫就緒=事件
epoll.modify(fd, select.EPOLLOUT)
#記錄數據
msgs.append((sock,data.upper()))
elif event == select.EPOLLOUT:
for item in msgs[:]:
if item[0] == sock:
sock.send(item[1])
msgs.remove(item)
# 切換關注事件為寫就緒
epoll.modify(fd,select.EPOLLIN)
數據庫
1什么是數據庫
數據庫就是存儲數據的倉庫
普通存儲數據的方式有兩種 一種是內存的臨時存儲 斷電后數據消失 還有一種通過硬盤存儲可以永久保存數據但是讀取數據較慢
效率較低,還有一個問題不可能所有組件運行在同一臺計算機上為什么?
一臺計算機的性能總歸有上限 例如淘寶雙11 雙12 用一臺計算機來做服務器的 配置再高都肯定吃不消,那怎么辦?
我們可以通過垂直擴展計算機的性能 一種直接提升計算機硬件 但是一臺機器的性能擴展總歸有極限 所以不可取
我們通過橫向擴展
添加更多的計算機 將程序的不同組件分別運行在不同的計算機上
帶來的優點:
性能提高 穩定性提高(可拔插式)
現在性能問題已經解決了 通過分布式的方式
但是這些組件雖然分布在各個計算機上 但是它們還是一個整體
也就是說你操作的數據文件還是是同一份
默認情況下 程序能訪問的數據 但是只有當前計算機。
訪問不同計算機上的文件數據
如何能訪問別的計算機上的文件呢?
只有一種辦法,通過網絡 通過網絡把你要什么數據告訴服務器 服務器在通過網絡把你要的數據發送給你,得需要使用socket ,需要配套的來一個服務器端 和 客戶端程序,把客戶端程序分發給各個python程序 python程序通過客戶端來鏈接服務器端 從而完成數據的讀寫
也就是說數據庫本質上就是一套C/S結構的TCP程序
我們完全可以自己來編寫這么一套軟件,但是需要考慮一下幾個問題
1.socket需不需實現并發? 必須要
2.既然是并發 還要考慮線程安全問題? 需要給文件操作加鎖
3.是不是任何計算機請求鏈接我都要接受呢? 不是需要進行用戶認證
4.單純的對本地計算機上的數據進行讀取 速度都是非常慢的硬盤上的數據有尋道尋址時間 平均延遲時間,速度太慢! 要想辦法提高數據的存取效率,通過索引。
到現在我們知道了要開發一款應用程序必須先解決上述四個問題,但是對于每一個公司而言,開發周期是非常重要的,不可能為了開發應用程序而先花大把時間來編寫數據庫程序,這便產生了專門的數據庫軟件廠商。寫出了專門的數據庫軟件。
常見數據庫
關系型數據庫
數據庫可以為數據與數據之間建立關聯關系,人是一條數據,他可能關聯著一個工作崗位數據。雙方可以通過自身找到對方
mysql sqlserver db2 等
非關系型
通關key value存儲數據各個數據之間沒有關系 不是通用性數據庫 有局限性,通常運行在將數據存儲在內存中,以提高速度,所以非關系性數據庫多用于緩存,與關系型數據庫搭配使用。
mongdb redis memcache 等
我們通常說的數據庫就是一套軟件 有服務端和客戶端 用來操作服務器端上的文件
數據庫相關概念
數據 用于記錄事物狀態信息 可以是數字 字符 聲音 圖片
記錄一條記錄用于保存一個事物的典型特征 就相當于文件中的一行
表 本質就是一個文件 創建表的時候其實就在創建一個文件
庫 本質就是一個文件夾
DBMS 數據庫管理軟件 就是一個套接字服務器端軟件
二.安裝mysql
1.下載安裝包
下載地址:https://dev.mysql.com/downloads/mysql/
下載的時候提供了帶界面的和不帶界面的 用哪個呢?
服務器通常是不帶界面的linux系統,并且熟練掌握SQL語句通常是面試官的基本要求
此處安裝解壓版的,下載對應的32/64位壓縮包,解壓到指定位置即可。
2.mysql目錄解析
"""
bin 執行文件
mysqld 服務器主程序
mysql 無界面的客戶端
data 數據文件
my-default.ini 配置文件模板
3.啟動mysql服務器
注意:5.7后的版本需要先初始化 執行:mysqld --initialize-insecure
'''
啟動服務器
1.運行CMD,通過cd 進入bin目錄
2.執行mysqld就可以啟動服務器,如果報錯的話使用管理員權限來運行CMD
這是一個socket服務器程序 這時候相當于做了一下事情:
啟動服務器socket 并監聽端口 默認綁定當前ip 端口默認3306
啟動客戶端
運行mysql 注意他是一個socket程序 要連接服務器需要ip 和 端口
mysql -h ip -P port -uroot -p 密碼默認為空
看到歡迎界面則說明socket鏈接成功了
?
執行過程分析:
這個命令提示符本質是什么?
就是一個input
接受一條指令然后發送給服務器
服務器接收到之后呢解析指令
取出你要的數據在send給客戶端
那問題來了 指令肯定不能隨便寫,不然服務器不認識,大家必須得有套規范
就是sql 語句
sql全稱為 結構化查詢語言,是所有非關系型數據庫都支持的語言,學習數據庫很大一部分時間是在學習sql語句。
登錄成功后可以執行一下命令來查看所有存在的數據庫
show databases;
對比data文件夾來看
那在講命令之前呢 思考一下 我們每次要使用mysql都得先cd到這個目錄中非常麻煩
怎么解決呢?
4.加到環境變量
找到安裝目錄,將bin路徑復制填入系統設置的path中即可
命令總結:
?
mysqld #啟動服務器
啟動客戶端 #mysql -h -P -u -p 本機簡寫 mysql -u -p
?
#關閉服務器
tasklist | findstr mysqld
taskkill /F /PID 8372
?
也可以直接退出CMD
5.注冊系統服務
服務器的啟動和關閉都需要執行命令 還是不夠方便 怎么辦呢?
'''
將mysql注冊到系統服務中 mysqld --install
需要注意的是 默認注冊的服務名稱叫做mysql 這與bin下的mysql是兩碼子事,一個系統服務一個是客戶端執行文件
?
刪除服務 sc delete mysql(服務名)
?
查看系統服務 運行->services.msc
通常設置為自動啟動。
如果注冊系統服務失敗則可能是因為你之前安裝過mysql 卸載重裝即可。
界面版的安裝失敗也可能是之前安裝了,導致端口占用。
三.修改管理員密碼
現在密碼默認為空 這樣是不安全的
萬一誰過來把你數據刪了 怎么辦?
?
#修改密碼
在知道原始密碼的情況下可以使用mysqladmin
mysqladmin是一個用于管理數據庫的程序,包括修改密碼,數據備份等
修改密碼:
mysqladmin -uroot -p舊密碼 password 123
警告忽略即可
?
#破解密碼:
萬一你不小心把密碼忘記了怎么辦? 到公司不可能卸載重裝
這個密碼它肯定要找地方存儲起來 ,那存客戶端還是服務器呢?
服務器 ,那存在內存還是硬盤呢? 必然是硬盤,既然如此,一定有一文件用于存放密碼信息
?
#方式1:刪除用于記錄用戶密碼數據文件
沒問題 簡單粗暴 但是,這個文件里不只有你的賬號信息 還有別人賬號數據 還有授權相關的數據
所以你最好不要這么干!
那你在思考一下,服務器驗證用戶的本質是什么,是不是讀取一個文件的數據來和你輸入的數據進行對比,
那你可不可以這樣子 我告訴我服務器說你不要去讀那個授權文件,可以!
?
#方式2: 跳過授權表 進入系統修改授權表推薦
跳過這個操作是服務器相關的操作所以 咱的先關掉服務器重新開 在重新開的時候來告訴它
1.停止服務
2.啟動服務器并添加參數
**mysqld --skip-grant-tables**
3.使用客戶端登錄服務器 執行修改命令 此時不需要輸入密碼
update mysql.user set password = password("123123") where user="root" and host="localhost"**
4.刷新權限
flush privileges
5.命令行中重啟服務器驗證新密碼
總結
- 上一篇: [家里蹲大学数学杂志]第036期泛函分析
- 下一篇: C++ 实现分数的四则运算