python面試題大全系列(二)

內(nèi)容主要包含網(wǎng)絡編程、數(shù)據(jù)庫和框架

1. 簡述 OSI 七層協(xié)議

OSI是網(wǎng)絡傳輸協(xié)議,人為的把網(wǎng)絡傳輸?shù)牟煌A段劃分成不同的層次

七層劃分為:應用層、表示層、會話層、傳輸層、網(wǎng)絡層、數(shù)據(jù)鏈路層、物理層。

五層劃分為:應用層、傳輸層、網(wǎng)絡層、數(shù)據(jù)鏈路層、物理層。

物理層:網(wǎng)線,電纜等物理設備

數(shù)據(jù)鏈路層:Mac 地址

網(wǎng)絡層:IP 地址

傳輸層:TCP,UDP 協(xié)議

應用層:FTP 協(xié)議,Email,WWW 等

2. 三次握手、四次揮手的流程

都發(fā)生在傳輸層

三次握手:

TCP 協(xié)議是主機對主機層的傳輸控制協(xié)議,提供可靠的連接服務,采用三次握手確認建立一個連接。

TCP 標志位(位碼),有6種標示:SYN(synchronous建立聯(lián)機) ACK(acknowledgement 確認) PSH(push傳送) FIN(finish結束) RST(reset重置) URG(urgent緊急)

Sequence number(順序號碼) Acknowledge number(確認號碼)

第一次握手:主機 A 發(fā)送位碼為 syn=1,隨機產(chǎn)生 seq number=1234567 的數(shù)據(jù)包到服務器,并進入 SYN_SEND 狀態(tài),主機 B 由 SYN=1 知道,A 要求建立聯(lián)機;

第二次握手:主機 B 收到請求后要確認聯(lián)機信息,向 A 發(fā)送 ack number=(主機 A 的 seq+1),syn=1,ack=1,隨機產(chǎn)生 seq=7654321 的包,并進入 SYN_RECV 狀態(tài);

第三次握手:主機 A 收到后檢查 ack number 是否正確,即第一次發(fā)送的 seq number+1,以及位碼 ack 是否為 1,若正確,主機 A 會再發(fā)送 ack number=(主機 B 的 seq+1),ack=1,主機 B 收到后確認 seq 值與 ack=1 則連接建立成功,兩個主機均進入 ESTABLISHED 狀態(tài)。

以上完成三次握手,主機 A 與主機 B 開始傳送數(shù)據(jù)。

四次揮手:

因為 TCP 連接是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的數(shù)據(jù)發(fā)送任務后就能發(fā)送一個 FIN 來終止這個方向的連接。收到一個 FIN 只意味著這一方向上沒有數(shù)據(jù)流動,一個 TCP 連接在收到一個 FIN 后仍能發(fā)送數(shù)據(jù)。首先進行關閉的一方將執(zhí)行主動關閉,而另一方執(zhí)行被動關閉。

(1)服務器 A 發(fā)送一個 FIN,用來關閉 A 到服務器 B 的數(shù)據(jù)傳送。

(2)服務器 B 收到這個 FIN,它發(fā)回一個 ACK,確認序號為收到的序號加1。和 SYN 一樣,一個 FIN 將占用一個序號。

(3)服務器 B 關閉與服務器 A 的連接,發(fā)送一個 FIN 給服務器 A。

(4)服務器 A 發(fā)回 ACK 報文確認,并將確認序號設置為收到序號加1。

3. 什么是 C/S 和 B/S 架構

B/S 又稱為瀏覽器/服務器模式。比如各種網(wǎng)站,jupyter notebook 等。

優(yōu)點:零安裝,維護簡單,共享性好。

缺點:安全性較差,個性化不足。

C/S 又稱為客戶端/服務器模式。比如微信客戶端,Oracle 客戶端等。

優(yōu)點:安全性好,數(shù)據(jù)傳輸較快,穩(wěn)定。

缺點:對 PC 機操作系統(tǒng)等有要求,當客戶端較多時,服務器端負載較大。

4. TCP 和 UDP 的區(qū)別

TCP 和 UDP 都是 OSI 模型中運輸層的協(xié)議。TCP 提供可靠的通信傳輸,而 UDP 則常被用于廣播和細節(jié)控制交給應用的通信傳輸。

UDP 不提供復雜的控制機制,利用 IP 提供面向無連接的通信服務。

TCP 充分實現(xiàn)了數(shù)據(jù)傳輸時各種控制功能,可以進行丟包的重發(fā)控制,還可以對次序亂掉的分包進行順序控制。

TCP 應用:FTP 傳輸,點對點短信等。

UDP 應用:媒體流等。

5. 局域網(wǎng)和廣域網(wǎng)

廣域網(wǎng)(WAN,Wide Area Network)也稱遠程網(wǎng)(long haul network )。通??缃雍艽蟮奈锢矸秶?,所覆蓋的范圍從幾十公里到幾千公里,它能連接多個城市或國家,或橫跨幾個洲并能提供遠距離通信,形成國際性的遠程網(wǎng)絡。

域網(wǎng)(Local Area Network,LAN)是指在某一區(qū)域內(nèi)由多臺計算機互聯(lián)成的計算機組。一般是方圓幾千米以內(nèi)。局域網(wǎng)可以實現(xiàn)文件管理、應用軟件共享、打印機共享、工作組內(nèi)的日程安排、電子郵件和傳真通信服務等功能。局域網(wǎng)是封閉型的,可以由辦公室內(nèi)的兩臺計算機組成,也可以由一個公司內(nèi)的上千臺計算機組成。

6. arp 協(xié)議

ARP(Address Resolution Protocol)即地址解析協(xié)議, 用于實現(xiàn)從 IP 地址到 MAC 地址的映射,即詢問目標 IP 對應的 MAC 地址。

7. 什么是 socket?簡述基于 TCP 協(xié)議的套接字通信流程。

socket 是對 TCP/IP 協(xié)議的封裝,它的出現(xiàn)只是使得程序員更方便地使用 TCP/IP 協(xié)議棧而已。socket 本身并不是協(xié)議,它是應用層與 TCP/IP 協(xié)議族通信的中間軟件抽象層,是一組調(diào)用接口(TCP/IP網(wǎng)絡的API函數(shù))。

“TCP/IP 只是一個協(xié)議棧,就像操作系統(tǒng)的運行機制一樣,必須要具體實現(xiàn),同時還要提供對外的操作接口。

這個就像操作系統(tǒng)會提供標準的編程接口,比如win32編程接口一樣。TCP/IP 也要提供可供程序員做網(wǎng)絡開發(fā)所用的接口,這就是 Socket 編程接口?!?/p>

Server:

import socket

import threading

def tcplink(sock, addr):

? ? print('Accept new connection from %s:%s...' % addr)

? ? sock.send(b'Welcome!')

? ? while True:

? ? ? ? data= sock.recv(1024)

? ? ? ? time.sleep(1)

? ? ? ? if not dataor data.decode('utf-8') == 'exit':

break

? ? ? ? sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))

? ? sock.close()

? ? print('Connection from %s:%s closed.' % addr)

s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 監(jiān)聽端口:

s.bind(('127.0.0.1', 9999))

s.listen(5)

print('Waiting for connection...')

while True:

? ? # 接受一個新連接:

? ? sock, addr= s.accept()

? ? # 創(chuàng)建新線程來處理TCP連接:

? ? t= threading.Thread(target=tcplink, args=(sock, addr))

? ? t.start()

Client:

import socket

s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 建立連接:

s.connect(('127.0.0.1', 9999))

# 接收歡迎消息:

print(s.recv(1024).decode('utf-8'))

for datain [b'Michael', b'Tracy', b'Sarah']:

? ? # 發(fā)送數(shù)據(jù):

? ? s.send(data)

? ? print(s.recv(1024).decode('utf-8'))

s.send(b'exit')

s.close()

8. 簡述 進程、線程、協(xié)程的區(qū)別以及應用場景

進程是具有一定獨立功能的程序關于某個數(shù)據(jù)集合上的一次運行活動,進程是系統(tǒng)進行資源分配和調(diào)度的一個獨立單位。每個進程都有自己的獨立內(nèi)存空間,不同進程通過進程間通信來通信。

線程是進程的一個實體,是CPU調(diào)度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己基本上不擁有系統(tǒng)資源,只擁有一點在運行中必不可少的資源(如程序計數(shù)器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。

協(xié)程是一種用戶態(tài)的輕量級線程,協(xié)程的調(diào)度完全由用戶控制。協(xié)程擁有自己的寄存器上下文和棧。

多進程:密集 CPU 任務,需要充分使用多核 CPU 資源(服務器,大量的并行計算)的時候,用多進程。

缺陷:多個進程之間通信成本高,切換開銷大。

多線程:密集 I/O 任務(網(wǎng)絡 I/O,磁盤 I/O,數(shù)據(jù)庫 I/O)使用多線程合適。

缺陷:同一個時間切片只能運行一個線程,不能做到高并行,但是可以做到高并發(fā)。

協(xié)程:又稱微線程,在單線程上執(zhí)行多個任務,用函數(shù)切換,開銷極小。不通過操作系統(tǒng)調(diào)度,沒有進程、線程的切換開銷。

缺陷:單線程執(zhí)行,處理密集 CPU 和本地磁盤 IO 的時候,性能較低。處理網(wǎng)絡 I/O 性能還是比較高。

多線程請求返回是無序的,哪個線程有數(shù)據(jù)返回就處理哪個線程,而協(xié)程返回的數(shù)據(jù)是有序的。

9. 如何使用線程池和進程池

池的功能是限制啟動的進程數(shù)或線程數(shù)。當并發(fā)的任務數(shù)遠遠超過了計算機的承受能力時,即無法一次性開啟過多的進程數(shù)或線程數(shù)時,就應該用池的概念將開啟的進程數(shù)或線程數(shù)限制在計算機可承受的范圍內(nèi)。

多進程

from multiprocessingimport Pool

import os

import time

import random

def long_time_task(name):

? ? print('Run task %s (%s)...' % (name, os.getpid()))

? ? start= time.time()

? ? time.sleep(random.random() * 3)

? ? end= time.time()

? ? print('Task %s runs %0.2f seconds.' % (name, (end- start)))

def test_pool():

? ? print('Parent process %s.' % os.getpid())

? ? p= Pool(4)

? ? for iin range(5):

? ? ? ? p.apply_async(long_time_task, args=(i,))

? ? print('Waiting for all subprocesses done...')

? ? p.close()

? ? p.join()

? ? print('All subprocesses done.')

if __name__== '__main__':

? ? test_pool()

apply_async(func[, args[, kwds]]) :使用非阻塞方式調(diào)用 func(并行執(zhí)行,堵塞方式必須等待上一個進程退出才能執(zhí)行下一個進程),args 為傳遞給 func 的參數(shù)列表,kwds 為傳遞給 func 的關鍵字參數(shù)列表;

close():關閉 Pool,使其不再接受新的任務;

terminate():不管任務是否完成,立即終止;

join():主進程阻塞,等待子進程的退出, 必須在 close 或 terminate 之后使用;

也可以使用 concurrent.futures 模塊提供的功能來實現(xiàn)

def test_future_process():

? ? print('Parent process %s.' % os.getpid())

? ? p= ProcessPoolExecutor(4)

? ? for iin range(5):

? ? ? ? p.submit(long_time_task, i)

? ? p.shutdown(wait=True)

? ? print('Finish')

if __name__== '__main__':

? ? # test_pool()

? ? test_future_process()

多線程

def sayhello(a):

? ? print("hello: " + a)

? ? start= time.time()

? ? time.sleep(random.random() * 3)

? ? end= time.time()

? ? print('Task %s runs %0.2f seconds.' % (a, (end- start)))

def test_future_thread():

? ? seed= ["a", "b", "c", "d"]

? ? start= time.time()

? ? with ThreadPoolExecutor(3) as executor:

? ? ? ? for iin seed:

? ? ? ? ? ? executor.submit(sayhello, i)

? ? end= time.time()

? ? print("Thread Run Time: " + str(end- start))

可以看出,由于是創(chuàng)建了限制為3的線程池,所以只有三個任務在同時執(zhí)行。

10. 進程之間如何進行通信

def write(q):

? ? print("write(%s), 父進程為(%s)" % (os.getpid(), os.getppid()))

? ? for iin "Python":

? ? ? ? print("Put %s to Queue" % i)

? ? ? ? q.put(i)

def read(q):

? ? print("read(%s), 父進程為(%s)" % (os.getpid(), os.getppid()))

? ? for iin range(q.qsize()):

? ? ? ? print("read 從 Queue 獲取到消息: %s" % q.get(True))

def test_commun():

? ? print("(%s) start" % os.getpid())

? ? q= Manager().Queue()

? ? pw= Process(target=write, args=(q, ))

? ? pr= Process(target=read, args=(q, ))

? ? pw.start()

? ? pr.start()

? ? pw.join()

? ? pr.terminate()

Python 的 multiprocessing 模塊包裝了底層的機制,提供了 Queue、Pipes 等多種方式來交換數(shù)據(jù)。

11. 進程鎖和線程鎖

進程鎖:是為了控制同一操作系統(tǒng)中多個進程訪問一個共享資源,只是因為程序的獨立性,各個進程是無法控制其他進程對資源的訪問的,但是可以使用本地系統(tǒng)的信號量控制。

信號量(Semaphore),有時被稱為信號燈,是在多線程環(huán)境下使用的一種設施,是可以用來保證兩個或多個關鍵代碼段不被并發(fā)調(diào)用。

線程鎖:當多個線程幾乎同時修改一個共享數(shù)據(jù)的時候,需要進行同步控制,線程同步能夠保證多個線程安全的訪問競爭資源(全局內(nèi)容),最簡單的同步機制就是使用互斥鎖。

某個線程要更改共享數(shù)據(jù)時,先將其鎖定,此時資源的狀態(tài)為鎖定狀態(tài),其他線程就能更改,直到該線程將資源狀態(tài)改為非鎖定狀態(tài),也就是釋放資源,其他的線程才能再次鎖定資源。互斥鎖保證了每一次只有一個線程進入寫入操作。從而保證了多線程下數(shù)據(jù)的安全性。

12. 什么是并發(fā)和并行

并行:多個 CPU 核心,不同的程序就分配給不同的 CPU 來運行??梢宰尪鄠€程序同時執(zhí)行。

并發(fā):單個 CPU 核心,在一個時間切片里一次只能運行一個程序,如果需要運行多個程序,則串行執(zhí)行。

13. threading.local 的作用

ThreadLocal 叫做線程本地變量,ThreadLocal 在每一個變量中都會創(chuàng)建一個副本,每個線程都可以訪問自己內(nèi)部的副本變量,對其他線程時不可見的,修改之后也不會影響到其他線程。

14. 什么是域名解析

域名解析是指將域名解析為 IP 地址。也有反向的“逆解析”,將 IP 通過 DNS 服務器查找到對應的域名地址。

DNS 是域名系統(tǒng) (Domain Name System),域名系統(tǒng)為因特網(wǎng)上的主機分配域名地址和 IP 地址。用戶使用域名地址,該系統(tǒng)就會自動把域名地址轉為 IP 地址。

15. LVS 是什么及作用

LVS 是 Linux Virtual Server 的簡寫,意即 Linux 虛擬服務器,是一個虛擬的服務器集群系統(tǒng),即負載均衡服務器。

LVS 工作模式分為 NAT 模式、TUN 模式、以及 DR 模式。

16. Nginx 的作用

Nginx 主要功能:1、反向代理 2、負載均衡 3、HTTP 服務器(包含動靜分離) 4、正向代理

正向代理:某些情況下,代理用戶去訪問服務器,需要手動設置代理服務器的 IP 和端口號。

反向代理:是用來代理服務器的,代理要訪問的目標服務器。代理服務器接受請求,然后將請求轉發(fā)給內(nèi)部網(wǎng)絡的服務器(集群化),并將從服務器上得到的結果返回給客戶端,此時代理服務器對外就表現(xiàn)為一個服務器。

負載均衡服務器類似于 LVS

HTTP 服務器類似于 Tomcat 等。

17. keepalived 及 HAProxy

HAProxy 提供高可用性、負載均衡,以及基于 TCP 和 HTTP 的應用程序代理。

keepalived 是集群管理中保證集群高可用的一個服務軟件,其功能類似于 heartbeat,用來防止單點故障。

18. 什么是 rpc

RPC 是指遠程過程調(diào)用,也就是說兩臺服務器 A,B,一個應用部署在 A 服務器上,想要調(diào)用 B 服務器上應用提供的函數(shù)/方法,由于不在一個內(nèi)存空間,不能直接調(diào)用,需要通過網(wǎng)絡來表達調(diào)用的語義和傳達調(diào)用的數(shù)據(jù)。

19. 從瀏覽器輸入一個網(wǎng)址到展示網(wǎng)址頁面的過程

瀏覽器通過 DNS 服務器查找到域名對應的 IP 地址

瀏覽器給 IP 對應的 web 服務器發(fā)送 HTTP 請求

web 服務器接收到 HTTP 請求后,返回響應給瀏覽器

瀏覽器接收到響應后渲染頁面

20. 什么是cdn

CDN 的全稱是 Content Delivery Network,即內(nèi)容分發(fā)網(wǎng)絡。CDN 是構建在網(wǎng)絡之上的內(nèi)容分發(fā)網(wǎng)絡,依靠部署在各地的邊緣服務器,通過中心平臺的負載均衡、內(nèi)容分發(fā)、調(diào)度等功能模塊,使用戶就近獲取所需內(nèi)容,降低網(wǎng)絡擁塞,提高用戶訪問響應速度和命中率。CDN 的關鍵技術主要有內(nèi)容存儲和分發(fā)技術。

二、數(shù)據(jù)庫和框架

1. 列舉常見的數(shù)據(jù)庫

關系型數(shù)據(jù)庫:MySQL,Oracle,SQLServer,SQLite,DB2

非關系型數(shù)據(jù)庫:MongoDB,Redis,HBase,Neo4j

2. 數(shù)據(jù)庫設計三大范式

建立科學的,規(guī)范的的數(shù)據(jù)庫是需要滿足一些規(guī)范的,以此來優(yōu)化數(shù)據(jù)數(shù)據(jù)存儲方式,在關系型數(shù)據(jù)庫中這些規(guī)范就可以稱為范式。

第一范式:當關系模式 R 的所有屬性都不能在分解為更基本的數(shù)據(jù)單位時,稱 R 是滿足第一范式的,簡記為 1NF。

關系模式R的所有屬性不能再分解

第二范式:如果關系模式 R 滿足第一范式,并且 R 的所有非主屬性都完全依賴于 R 的每一個候選關鍵屬性,稱 R 滿足第二范式,簡記為 2NF。

非主屬性都要依賴于每一個關鍵屬性

三范式:設 R 是一個滿足第一范式條件的關系模式,X 是 R 的任意屬性集,如果 X 非傳遞依賴于 R 的任意一個候選關鍵字,稱 R 滿足第三范式,簡記為 3NF。

數(shù)據(jù)不能存在傳遞關系,即每個屬性都跟主鍵有直接關系而不是間接關系

3. 什么是數(shù)據(jù)庫事務

事務(Transaction)是并發(fā)控制的基本單位。所謂的事務,它是一個操作序列,這些操作要么都執(zhí)行,要么都不執(zhí)行,它是一個不可分割的工作單位。

在關系數(shù)據(jù)庫中,一個事務可以是一條 SQL 語句、一組 SQL 語句或整個程序。

四個屬性:原子性,一致性,隔離性和持久性。

4. MySQL 索引種類

MySQL 目前主要有以下幾種索引類型:

(1)普通索引

(2)唯一索引

(3)主鍵索引

(4)組合索引

(5)全文索引

5. 數(shù)據(jù)庫設計中一對多和多對多的應用場景

一對一關系示例:

一個學生對應一個學生檔案材料,或者每個人都有唯一的身份證編號。

一對多關系示例:

一個學生只屬于一個班,但是一個班級有多名學生。

多對多關系示例:

一個學生可以選擇多門課,一門課也有多名學生。

6. 簡述觸發(fā)器、函數(shù)、視圖、存儲過程

觸發(fā)器:觸發(fā)器是一個特殊的存儲過程,它是數(shù)據(jù)庫在 insert、update、delete 的時候自動執(zhí)行的代碼塊。

函數(shù):數(shù)據(jù)庫中提供了許多內(nèi)置函數(shù),還可以自定義函數(shù),實現(xiàn) sql 邏輯。

視圖:視圖是由查詢結果形成的一張?zhí)摂M表,是表通過某種運算得到的一個投影

存儲過程:把一段代碼封裝起來,當要執(zhí)行這一段代碼的時候,可以通過調(diào)用該存儲過程來實現(xiàn)(經(jīng)過第一次編譯后再次調(diào)用不需要再次編譯,比一個個執(zhí)行 sql 語句效率高)

7. 常用 SQL 語句

DML(數(shù)據(jù)操作語言)

(1)SELECT - 從數(shù)據(jù)庫表中獲取數(shù)據(jù)

(2)UPDATE - 更新數(shù)據(jù)庫表中的數(shù)據(jù)

(3)DELETE - 從數(shù)據(jù)庫表中刪除數(shù)據(jù)

(4)INSERT INTO - 向數(shù)據(jù)庫表中插入數(shù)據(jù)

DDL(數(shù)據(jù)定義語言)

(1)CREATE DATABASE - 創(chuàng)建新數(shù)據(jù)庫

(2)ALTER DATABASE - 修改數(shù)據(jù)庫

(3)CREATE TABLE - 創(chuàng)建新表

(4)ALTER TABLE - 變更(改變)數(shù)據(jù)庫表

(5)DROP TABLE - 刪除表

(6)CREATE INDEX - 創(chuàng)建索引(搜索鍵)

(7)DROP INDEX - 刪除索引

8. 主鍵和外鍵的區(qū)別

定義主鍵和外鍵主要是為了維護關系數(shù)據(jù)庫的完整性

主鍵是能確定一條記錄的唯一標識。不能重復,不允許為空。

外鍵用于與另一張表關聯(lián)。是能確定另一張表記錄的字段,用于保持數(shù)據(jù)的一致性。

9. 如何開啟 MySQL 慢日志查詢

(1)修改配置文件,然后重啟服務生效

在linux下,vim /etc/my.cnf,在[mysqld]內(nèi)容項下增加:

slow_query_log = ON

long_query_time = 2 ?# 查詢超過2秒的就會記錄

(2)命令行,但是重啟服務后會失效

SET GLOBAL slow_query_log = 'ON';

SET GLOBAL long_query_time = 2;

10. MySQL 數(shù)據(jù)庫備份命令

mysqldump -u 用戶名 -p 數(shù)據(jù)庫名 > 導出的文件名

11. char 和 varchar 的區(qū)別

char:存儲定長數(shù)據(jù)很方便,CHAR 字段上的索引效率級高,必須在括號里定義長度,可以有默認值,比如定義 char(10)。

varchar:存儲變長數(shù)據(jù),但存儲效率沒有 CHAR 高,必須在括號里定義長度,可以有默認值。

12. 最左前綴原則

mysql 建立多列索引(聯(lián)合索引)有最左前綴的原則,即最左優(yōu)先,如:

如果有一個2列的索引(col1,col2),則已經(jīng)對(col1)、(col1,col2)上建立了索引;

如果有一個3列索引(col1,col2,col3),則已經(jīng)對(col1)、(col1,col2)、(col1,col2,col3)上建立了索引;

13. 無法命中索引的情況

(1)使用or關鍵字會導致無法命中索引

(2)左前導查詢會導致無法命中索引,如 like '%a' 或者 like '%a%'

(3)單列索引的索引列為 null 時全值匹配會使索引失效,組合索引全為 null 時索引失效

(4)組合索引不符合左前綴原則的列無法命中索引,如我們有4個列 a、b、c、d,我們創(chuàng)建一個組合索引 INDEX(a,b,c,d),那么能命中索引的查詢?yōu)?a,ab,abc,abcd,除此之外都無法命中索引

(5)強制類型轉換會導致索引失效

(6)負向查詢條件會導致無法使用索引,比如 NOT IN,NOT LIKE,!= 等

(7)如果 mysql 估計使用全表掃描要比使用索引快,則不使用索引

14. 數(shù)據(jù)庫讀寫分離

讀寫分離,就是將數(shù)據(jù)庫分為了主從庫,一個主庫用于寫數(shù)據(jù),多個從庫完成讀數(shù)據(jù)的操作,主從庫之間通過某種機制進行數(shù)據(jù)的同步,是一種常見的數(shù)據(jù)庫架構。

15. 數(shù)據(jù)庫分庫分表

數(shù)據(jù)庫水平切分,是一種常見的數(shù)據(jù)庫架構,是一種通過算法,將數(shù)據(jù)庫進行分割的架構。一個水平切分集群中的每個數(shù)據(jù)庫,通常稱為一個“分片”。每一個分片中的數(shù)據(jù)沒有重合,所有分片中的數(shù)據(jù)并集組成全部數(shù)據(jù)。

水平切分分為庫內(nèi)分表和分庫分表,是根據(jù)表內(nèi)數(shù)據(jù)內(nèi)在的邏輯關系,將同一個表按不同的條件分散到多個數(shù)據(jù)庫或多個表中,每個表中只包含一部分數(shù)據(jù),從而使得單個表的數(shù)據(jù)量變小,達到分布式的效果。

16. redis 和 memcached 比較

redis 和 memcached 都是將數(shù)據(jù)存放在內(nèi)存中,都是內(nèi)存數(shù)據(jù)庫。不過 memcached 還可用于緩存其他東西,例如圖片、視頻等等。

redis 不僅僅支持簡單的 k/v 類型的數(shù)據(jù),同時還提供 list,set,hash 等數(shù)據(jù)結構的存儲。

分布式設定, 都可以做一主多從或一主一從 。

存儲數(shù)據(jù)安全,memcached 掛掉后,數(shù)據(jù)完全丟失;redis 可以定期保存到磁盤(持久化)。

災難恢復,memcached 掛掉后,數(shù)據(jù)不可恢復; redis 數(shù)據(jù)丟失后可以通過 aof 恢復。

17. redis中數(shù)據(jù)庫默認是多少個 db 及作用

redis 默認有16個數(shù)據(jù)庫,每個數(shù)據(jù)庫中的數(shù)據(jù)都是隔離的,這樣,在存儲數(shù)據(jù)的時候,就可以指定把不同的數(shù)據(jù)存儲到不同的數(shù)據(jù)庫中。

且只有單機才有,如果是集群就沒有數(shù)據(jù)庫的概念。

18. redis 有哪幾種持久化策略

RDB 持久化:是將 Reids 在內(nèi)存中的數(shù)據(jù)庫記錄定時 dump 到磁盤上的持久化

AOF(append only file)持久化:將 Reids 的操作日志以追加的方式寫入文件

19. redis 支持的過期策略

通用的三種過期策略

(1)定時刪除

在設置 key 的過期時間的同時,為該 key 創(chuàng)建一個定時器,讓定時器在 key 的過期時間來臨時,對 key 進行刪除

(2)惰性刪除

key 過期的時候不刪除,每次從數(shù)據(jù)庫獲取 key 的時候去檢查是否過期,若過期,則刪除,返回 null。

(3)定期刪除

每隔一段時間執(zhí)行一次刪除過期 key 操作

redis 采用惰性刪除+定期刪除策略

20. 如何保證 redis 中的數(shù)據(jù)都是熱點數(shù)據(jù)

限定 Redis 占用的內(nèi)存,Redis 會根據(jù)自身數(shù)據(jù)淘汰策略,加載熱數(shù)據(jù)到內(nèi)存。

所以,計算一下所有熱點數(shù)據(jù)大約占用的內(nèi)存,然后設置一下 Redis 內(nèi)存限制即可。

21. Python 操作 redis

使用 redis 第三方庫來操作

import redis

# 創(chuàng)建一個 redis 連接池

def redis_conn_pool():

? ? pool= redis.ConnectionPool(host='redis-host', port=redis-port,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? decode_responses=True, password='redis-pwd')

? ? r= redis.Redis(connection_pool=pool)

? ? return r

22. 基于 redis 實現(xiàn)發(fā)布和訂閱

訂閱者:

if __name__== "__main__":

? ? conn= redis.Redis(host='',

? ? ? ? ? ? ? ? ? ? ? port=12143, password='')

? ? ps= conn.pubsub()

? ? ps.subscribe('chat')? # 從 chat 訂閱消息

? ? for itemin ps.listen():? # 監(jiān)聽狀態(tài):有消息發(fā)布了就拿過來

? ? ? ? if item['type'] == 'message':

? ? ? ? ? ? print(item)

? ? ? ? ? ? print(item['channel'])

? ? ? ? ? ? print(item['data'])

發(fā)布者:

if __name__== "__main__":

? ? number_list= ['300033', '300032', '300031', '300030']

? ? signal= ['1', '-1', '1', '-1']

? ? pool= redis.ConnectionPool(host='redis-12143.c8.us-east-1-3.ec2.cloud.redislabs.com', port=12143,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? decode_responses=True, password='pkAWNdYWfbLLfNOfxTJinm9SO16eSJFx')

? ? r= redis.Redis(connection_pool=pool)

? ? for iin range(len(number_list)):

? ? ? ? value_new= str(number_list[i]) + ' ' + str(signal[i])

? ? ? ? print(value_new)

? ? ? ? r.publish("chat", value_new)

23. 如何高效的找到 redis 中的某個 KEY

import redis

con= redis.Redis()

con.keys(pattern='key*') # *代表通配符

24. 基于 redis 實現(xiàn)先進先出、后進先出及優(yōu)先級隊列

class Dui:

? ? def __init__(self,conn):

? ? ? ? self.conn= conn

? ? def push(self,val):

? ? ? ? self.conn.rpush('bbb',val)

? ? def get(self):

? ? ? ? return self.conn.lpop('bbb')

class Xu:

? ? def __init__(self,conn):

? ? ? ? self.conn= conn

? ? def push(self,val,count):

? ? ? ? self.conn.zadd('ccc',val,count)

? ? def get(self):

? ? ? ? a= self.conn.zrange('ccc', 0, 0)[0]

? ? ? ? self.conn.zrem('ccc', a)

? ? ? ? return a

25. redis 如何實現(xiàn)主從復制

在從服務器中配置 SLAVEOF 127.0.0.1 6380 # 主服務器 IP,端口

26. 循環(huán)獲取 redis 中某個非常大的列表數(shù)據(jù)

def list_iter(name):

? ? """

? ? 自定義redis列表增量迭代

? ? :param name: redis中的name,即:迭代name對應的列表

? ? :return: yield 返回 列表元素"""

? ? list_count= r.llen(name)

? ? for indexin xrange(list_count):

? ? ? ? yield r.lindex(name, index)

27. redis 中的 watch 的命令的作用

watch 用于在進行事務操作的最后一步也就是在執(zhí)行 exec 之前對某個 key 進行監(jiān)視,如果這個被監(jiān)視的 key 被改動,那么事務就被取消,否則事務正常執(zhí)行。

28. redis 分布式鎖

為 redis 集群設計的鎖,防止多個任務同時修改數(shù)據(jù)庫,其本質(zhì)就是為集群中的每個主機設置一個會超時的字符串,當集群中有一半多的機器設置成功后就認為加鎖成功,直至鎖過期或解鎖不會有第二個任務加鎖成功。

29. http 協(xié)議

超文本傳輸協(xié)議(HTTP,HyperText Transfer Protocol)是互聯(lián)網(wǎng)上應用最為廣泛的一種網(wǎng)絡協(xié)議。HTTP 是一個客戶端和服務器端請求和應答的標準??蛻舳耸墙K端用戶,服務器端是網(wǎng)站。一般由 HTTP 客戶端發(fā)起一個請求,建立一個到服務器指定端口(默認是80端口)的 TCP 連接,HTTP 服務器則在那個端口監(jiān)聽客戶端發(fā)送過來的請求,并給與響應。

30. uwsgi,uWSGI 和 WSGI 的區(qū)別

WSGI:全稱是 Web Server Gateway Interface,是一種描述 web server 如何與 web application 通信的規(guī)范。django,flask 等都遵循該協(xié)議。

uwsgi:是服務器和服務端應用程序的一種協(xié)議,規(guī)定了怎么把請求轉發(fā)給應用程序和返回; uwsgi 是一種線路協(xié)議而不是通信協(xié)議,在此常用于在 uWSGI 服務器與其他網(wǎng)絡服務器的數(shù)據(jù)通信。

uWSGI:是一個 Web 服務器,它實現(xiàn)了 WSGI 協(xié)議、uwsgi、http 等協(xié)議。Nginx 中 HttpUwsgiModule 的作用是與 uWSGI 服務器進行交換。

31. HTTP 狀態(tài)碼

1xx: 信息

2xx:成功

3xx:重定向

4xx:客戶端錯誤

5xx:服務器錯誤

32. HTTP常見請求方式

GET,POST,PUT,DELETE,PATCH 等

33. 響應式布局

響應式布局是 Ethan Marcotte 在2010年5月份提出的一個概念,簡而言之,就是一個網(wǎng)站能夠兼容多個終端——而不是為每個終端做一個特定的版本。

34. 實現(xiàn)一個簡單的 AJAX 請求

AJAX 是一種在無需重新加載整個網(wǎng)頁的情況下,能夠更新部分網(wǎng)頁的技術。

AJAX = 異步 JavaScript 和 XML

$(function(){

? $('#send').click(function(){

? ? ? ? $.ajax({

? ? ? ? ? ? type: "GET",

? ? ? ? ? ? url: "test.json",

? ? ? ? ? ? data: {username:$("#username").val(), content:$("#content").val()},

? ? ? ? ? ? dataType: "json",

? ? ? ? ? ? success: function(data){

? ? ? ? ? ? ? ? ? ? ? ? $('#resText').empty();//清空resText里面的所有內(nèi)容

? ? ? ? ? ? ? ? ? ? ? ? var html= '';

$.each(data, function(commentIndex, comment){

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? html+= '<div class="comment"><h6>' + comment['username']

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + ':</h6><p class="para"' + comment['content']

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + '</p></div>';

});

$('#resText').html(html);

}

? ? ? ? });

});

);

35. 同源策略

同源策略限制了從同一個源加載的文檔或腳本如何與來自另一個源的資源進行交互。這是一個用于隔離潛在惡意文件的重要安全機制。

如果兩個頁面的協(xié)議,端口(如果有指定)和主機都相同,則兩個頁面具有相同的源。我們也可以把它稱為“協(xié)議/主機/端口 tuple”,或簡單地叫做“tuple". ("tuple" ,“元”,是指一些事物組合在一起形成一個整體,比如(1,2)叫二元,(1,2,3)叫三元)

36. 什么是 CORS

CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing),是一種 AJAX 跨域請求資源的方式,支持現(xiàn)代瀏覽器。

37. 什么是 CSRF

CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。

38. 前端實現(xiàn)輪詢、長輪詢

輪詢:

var xhr= newXMLHttpRequest();

setInterval(function(){

? ? ? ? xhr.open('GET','/user');

xhr.onreadystatechange= function(){

? ? ? ? };

xhr.send();

},1000)

長輪詢:

functionajax(){

? ? ? ? var xhr= newXMLHttpRequest();

xhr.open('GET','/user');

xhr.onreadystatechange= function(){

? ? ? ? ? ? ? ajax();

};

xhr.send();

}

39. 簡述 MVC 和 MTV

所謂 MVC 就是把 web 應用分為模型(M),控制器(C),視圖(V)三層,他們之間以一種插件似的,松耦合的方式連接在一起。

模型負責業(yè)務對象與數(shù)據(jù)庫的對象(ORM),視圖負責與用戶的交互(頁面),控制器(C)接受用戶的輸入調(diào)用模型和視圖完成用戶的請求。

Django 中的 MTV 模式:Model(模型):負責業(yè)務對象與數(shù)據(jù)庫的對象(ORM),Template(模版):負責如何把頁面展示給用戶,View(視圖):負責業(yè)務邏輯,并在適當?shù)臅r候調(diào)用 Model 和 Template,本質(zhì)上與 MVC 相同。

40. 接口的冪等性

接口冪等性就是用戶對于同一操作發(fā)起的一次請求或者多次請求的結果是一致的,不會因為多次點擊而產(chǎn)生了副作用。

41. Flask 框架的優(yōu)勢

簡潔,輕巧,擴展性強,自由度高。

42. 什么是 ORM

ORM 的全稱是 Object Relational Mapping,即對象關系映射。它的實現(xiàn)思想就是將關系數(shù)據(jù)庫中表的數(shù)據(jù)映射成為對象,以對象的形式展現(xiàn),這樣開發(fā)人員就可以把對數(shù)據(jù)庫的操作轉化為對這些對象的操作。

43. PV、UV 的含義

PV:是(page view)訪問量,頁面瀏覽量或點擊量,衡量網(wǎng)站用戶訪問的網(wǎng)頁數(shù)量。在一定統(tǒng)計周期內(nèi)用戶每打開或刷新一個頁面就記錄1次,多次打開或刷新同一頁面則瀏覽量累計。

UV:是(Unique Visitor)獨立訪客,統(tǒng)計一段時間內(nèi)訪問某站點的用戶數(shù)(以cookie為依據(jù))。

44. supervisor 的作用

supervisor 管理進程,是通過 fork/exec 的方式將這些被管理的進程當作 supervisor 的子進程來啟動,所以我們只需要將要管理進程的可執(zhí)行文件的路徑添加到 supervisor 的配置文件中即可。

45. 使用 ORM 和原生 SQL 的優(yōu)缺點

優(yōu)點:

(1)方便的使用面向?qū)ο?,語句清晰;

(2)有效的防止 SQL 注入;

(3)方便動態(tài)構造語句,對于不同的表的相同操作采用多態(tài)實現(xiàn)更優(yōu)雅;

(4)一定程度上方便重構數(shù)據(jù)層

(5)方便設置設置鉤子函數(shù)

缺點:

(1)不太容易處理復雜查詢語句

(2)性能較直接用 SQL 差

46. 列舉一些 django 的內(nèi)置組件

(1)Admin 組件:是對 model 中對應的數(shù)據(jù)表進行增刪改查提供的組件

(2)model 組件:負責操作數(shù)據(jù)庫

(3)form 組件:生成 HTML 代碼;數(shù)據(jù)有效性校驗;校驗信息返回并展示

(4)ModelForm 組件:用于數(shù)據(jù)庫操作,也可用于用戶請求的驗證

47. 列舉 Django 中執(zhí)行原生 sql 的方法

(1)使用 execute 執(zhí)行自定義的 SQL

直接執(zhí)行 SQL 語句(類似于 pymysql 的用法)

from django.dbimport connection

cursor= connection.cursor()

cursor.execute("SELECT DATE_FORMAT(create_time, '%Y-%m') FROM blog_article;")

ret= cursor.fetchall()

print(ret)

(2)使用 extra 方法:queryset.extra(select={"key": "原生的SQL語句"})

(3)使用 raw 方法

? ? ? ? a.執(zhí)行原始 sql 并返回模型

? ? ? ? b.依賴于 model 模型,多用于查詢操作

48. cookie 和 session 的區(qū)別

cookie 是保存在瀏覽器端的鍵值對,可以用來做用戶認證。

sesseion 是將用戶的會話信息保存在服務端,key 值是隨機產(chǎn)生的字符串,value 值是 session 的內(nèi)容,依賴于 cookie 將每個用戶的隨機字符串保存到用戶瀏覽器中。

49. beautifulsoup 模塊的作用

BeautifulSoup 庫是解析、遍歷、維護“標簽樹”的功能庫。

url= "http://www.baidu.com/"

request= requests.get(url)

html= request.content

soup= BeautifulSoup(html, "html.parser", from_encoding="utf-8")

50. Selenium 模塊簡述

Selenium 是模擬操作瀏覽器的庫,可以根據(jù)我們的指令,讓瀏覽器自動加載頁面,獲取需要的數(shù)據(jù),甚至頁面截屏,或者判斷網(wǎng)站上某些動作是否發(fā)生等。

from seleniumimport webdriver

browser= webdriver.Chrome()

browser.get('https://www.taobao.com')

print(browser.page_source) # browser.page_source 是獲取網(wǎng)頁的全部html

browser.close()

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容