Python 必備面試基礎知識-3

今天繼續分享 Python 相關的面試題,你準備好了嘛!html

網絡編程篇前端

1. 簡述 OSI 七層協議

是網絡傳輸協議,人爲的把網絡傳輸的不一樣階段劃分紅不一樣的層次。mysql

七層劃分爲:應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層。linux

五層劃分爲:應用層、傳輸層、網絡層、數據鏈路層、物理層。程序員

物理層:網線,電纜等物理設備 數據鏈路層:Mac 地址 網絡層:IP 地址 傳輸層:TCP,UDP 協議 應用層:FTP 協議,Email,WWW 等web

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

都發生在傳輸層面試

三次握手:

TCP 協議是主機對主機層的傳輸控制協議,提供可靠的鏈接服務,採用三次握手確認創建一個鏈接。ajax

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

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

第一次握手:主機 A 發送位碼爲 syn=1,隨機產生 seq number=1234567 的數據包到服務器,並進入 SYN_SEND 狀態,主機 B 由 SYN=1 知道,A 要求創建聯機;

第二次握手:主機 B 收到請求後要確認聯機信息,向 A 發送 ack number=(主機 A 的 seq+1),syn=1,ack=1,隨機產生 seq=7654321 的包,並進入 SYN_RECV 狀態;

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

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

四次揮手:

由於 TCP 鏈接是全雙工的,所以每一個方向都必須單獨進行關閉。這個原則是當一方完成它的數據發送任務後就能發送一個 FIN 來終止這個方向的鏈接。收到一個 FIN 只意味着這一方向上沒有數據流動,一個 TCP 鏈接在收到一個 FIN 後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另外一方執行被動關閉。

  1. 服務器 A 發送一個 FIN,用來關閉 A 到服務器 B 的數據傳送。
  2. 服務器 B 收到這個 FIN,它發回一個 ACK,確認序號爲收到的序號加1。和 SYN 同樣,一個 FIN 將佔用一個序號。
  3. 服務器 B 關閉與服務器 A 的鏈接,發送一個 FIN 給服務器 A。
  4. 服務器 A 發回 ACK 報文確認,並將確認序號設置爲收到序號加1。

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

B/S 又稱爲瀏覽器/服務器模式。好比各類網站,jupyter notebook 等。

優勢:零安裝,維護簡單,共享性好。

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

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

優勢:安全性好,數據傳輸較快,穩定。

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

4. TCP和UDP的區別

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

UDP 不提供複雜的控制機制,利用 IP 提供面向無鏈接的通訊服務。

TCP 充分實現了數據傳輸時各類控制功能,能夠進行丟包的重發控制,還能夠對次序亂掉的分包進行順序控制。

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

UDP 應用:媒體流等。

5. 局域網和廣域網

廣域網(WAN,Wide Area Network)也稱遠程網(long haul network )。一般跨接很大的物理範圍,所覆蓋的範圍從幾十千米到幾千千米,它能鏈接多個城市或國家,或橫跨幾個洲並能提供遠距離通訊,造成國際性的遠程網絡。

局域網(Local Area Network,LAN)是指在某一區域內由多臺計算機互聯成的計算機組。通常是方圓幾公里之內。局域網能夠實現文件管理、應用軟件共享、打印機共享、工做組內的日程安排、電子郵件和傳真通訊服務等功能。局域網是封閉型的,能夠由辦公室內的兩臺計算機組成,也能夠由一個公司內的上千臺計算機組成。

6. arp 協議

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

7. 什麼是 socket?簡述基於 TCP 協議的套接字通訊流程。

socket 是對 TCP/IP 協議的封裝,它的出現只是使得程序員更方便地使用 TCP/IP 協議棧而已。socket 自己並非協議,它是應用層與 TCP/IP 協議族通訊的中間軟件抽象層,是一組調用接口(TCP/IP網絡的API函數)。

「TCP/IP 只是一個協議棧,就像操做系統的運行機制同樣,必需要具體實現,同時還要提供對外的操做接口。 這個就像操做系統會提供標準的編程接口,好比win32編程接口同樣。TCP/IP 也要提供可供程序員作網絡開發所用的接口,這就是 Socket 編程接口。」

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 data or 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)
# 監聽端口:
s.bind(('127.0.0.1', 9999))
s.listen(5)
print('Waiting for connection...')
while True:
    # 接受一個新鏈接:
    sock, addr = s.accept()
    # 建立新線程來處理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 data in [b'Michael', b'Tracy', b'Sarah']:
    # 發送數據:
    s.send(data)
    print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()
複製代碼

例子來源於廖雪峯的官網

8. 簡述 進程、線程、協程的區別以及應用場景

進程是具備必定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。每一個進程都有本身的獨立內存空間,不一樣進程經過進程間通訊來通訊。

線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程本身基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),可是它可與同屬一個進程的其餘的線程共享進程所擁有的所有資源。

協程是一種用戶態的輕量級線程,協程的調度徹底由用戶控制。協程擁有本身的寄存器上下文和棧。

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

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

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

缺陷:同一個時間切片只能運行一個線程,不能作到高並行,可是能夠作到高併發。

協程:又稱微線程,在單線程上執行多個任務,用函數切換,開銷極小。不經過操做系統調度,沒有進程、線程的切換開銷。

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

多線程請求返回是無序的,哪一個線程有數據返回就處理哪一個線程,而協程返回的數據是有序的。

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

池的功能是限制啓動的進程數或線程數。當併發的任務數遠遠超過了計算機的承受能力時,即沒法一次性開啓過多的進程數或線程數時,就應該用池的概念將開啓的進程數或線程數限制在計算機可承受的範圍內。

多進程

from multiprocessing import 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 i in 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()
複製代碼

output

Parent process 32432.
Waiting for all subprocesses done...
Run task 0 (15588)...
Run task 1 (32372)...
Run task 2 (12440)...
Run task 3 (18956)...
Task 2 runs 0.72 seconds.
Run task 4 (12440)...
Task 3 runs 0.82 seconds.
Task 1 runs 1.21 seconds.
Task 0 runs 3.00 seconds.
Task 4 runs 2.95 seconds.
All subprocesses done.
複製代碼

apply_async(func[, args[, kwds]]) :使用非阻塞方式調用 func(並行執行,堵塞方式必須等待上一個進程退出才能執行下一個進程),args 爲傳遞給 func 的參數列表,kwds 爲傳遞給 func 的關鍵字參數列表; close():關閉 Pool,使其再也不接受新的任務; terminate():無論任務是否完成,當即終止; join():主進程阻塞,等待子進程的退出, 必須在 close 或 terminate 以後使用;

也可使用 concurrent.futures 模塊提供的功能來實現

def test_future_process():
    print('Parent process %s.' % os.getpid())
    p = ProcessPoolExecutor(4)
    for i in range(5):
        p.submit(long_time_task, i)
    p.shutdown(wait=True)
    print('Finish')


if __name__ == '__main__':
    # test_pool()
    test_future_process()
複製代碼

output

Parent process 29368.
Run task 0 (32148)...
Run task 1 (31552)...
Run task 2 (24012)...
Run task 3 (29408)...
Task 2 runs 0.52 seconds.
Run task 4 (24012)...
Task 3 runs 0.86 seconds.
Task 1 runs 1.81 seconds.
Task 0 runs 1.83 seconds.
Task 4 runs 1.69 seconds.
Finish
複製代碼

多線程

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 i in seed:
            executor.submit(sayhello, i)
    end = time.time()
    print("Thread Run Time: " + str(end - start))
複製代碼

output

hello: a
hello: b
hello: c
Task a runs 0.40 seconds.
hello: d
Task b runs 0.56 seconds.
Task d runs 1.70 seconds.
Task c runs 2.92 seconds.
Thread Run Time: 2.9195945262908936
複製代碼

能夠看出,因爲是建立了限制爲3的線程池,因此只有三個任務在同時執行。

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

def write(q):
    print("write(%s), 父進程爲(%s)" % (os.getpid(), os.getppid()))
    for i in "Python":
        print("Put %s to Queue" % i)
        q.put(i)


def read(q):
    print("read(%s), 父進程爲(%s)" % (os.getpid(), os.getppid()))
    for i in 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()
複製代碼

output

(23544) start
write(29856), 父進程爲(23544)
Put P to Queue
Put y to Queue
Put t to Queue
Put h to Queue
Put o to Queue
Put n to Queue
read(25016), 父進程爲(23544)
read 從 Queue 獲取到消息: P
read 從 Queue 獲取到消息: y
read 從 Queue 獲取到消息: t
read 從 Queue 獲取到消息: h
read 從 Queue 獲取到消息: o
read 從 Queue 獲取到消息: n
複製代碼

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

11. 進程鎖和線程鎖

進程鎖:是爲了控制同一操做系統中多個進程訪問一個共享資源,只是由於程序的獨立性,各個進程是沒法控制其餘進程對資源的訪問的,可是可使用本地系統的信號量控制。

信號量(Semaphore),有時被稱爲信號燈,是在多線程環境下使用的一種設施,是能夠用來保證兩個或多個關鍵代碼段不被併發調用。

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

某個線程要更改共享數據時,先將其鎖定,此時資源的狀態爲鎖定狀態,其餘線程就能更改,直到該線程將資源狀態改成非鎖定狀態,也就是釋放資源,其餘的線程才能再次鎖定資源。互斥鎖保證了每一次只有一個線程進入寫入操做。從而保證了多線程下數據的安全性。

12. 什麼是併發和並行

並行:多個 CPU 核心,不一樣的程序就分配給不一樣的 CPU 來運行。可讓多個程序同時執行。

併發:單個 CPU 核心,在一個時間切片裏一次只能運行一個程序,若是須要運行多個程序,則串行執行。

13. threading.local 的做用

ThreadLocal 叫作線程本地變量,ThreadLocal 在每個變量中都會建立一個副本,每一個線程均可以訪問本身內部的副本變量,對其餘線程時不可見的,修改以後也不會影響到其餘線程。

14. 什麼是域名解析

域名解析是指將域名解析爲 IP 地址。也有反向的「逆解析」,將 IP 經過 DNS 服務器查找到對應的域名地址。

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

15. LVS 是什麼及做用

LVS 是 Linux Virtual Server 的簡寫,意即 Linux 虛擬服務器,是一個虛擬的服務器集羣系統,即負載均衡服務器。

LVS 工做模式分爲 NAT 模式、TUN 模式、以及 DR 模式。

16. Nginx 的做用

Nginx 主要功能:一、反向代理 二、負載均衡 三、HTTP 服務器(包含動靜分離) 四、正向代理

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

反向代理:是用來代理服務器的,代理要訪問的目標服務器。代理服務器接受請求,而後將請求轉發給內部網絡的服務器(集羣化),並將從服務器上獲得的結果返回給客戶端,此時代理服務器對外就表現爲一個服務器。

負載均衡服務器相似於 LVS HTTP 服務器相似於 Tomcat 等。

17. keepalived 及 HAProxy

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

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

18. 什麼是 rpc

RPC 是指遠程過程調用,也就是說兩臺服務器 A,B,一個應用部署在 A 服務器上,想要調用 B 服務器上應用提供的函數/方法,因爲不在一個內存空間,不能直接調用,須要經過網絡來表達調用的語義和傳達調用的數據。

19. 從瀏覽器輸入一個網址到展現網址頁面的過程

  1. 瀏覽器經過 DNS 服務器查找到域名對應的 IP 地址
  2. 瀏覽器給 IP 對應的 web 服務器發送 HTTP 請求
  3. web 服務器接收到 HTTP 請求後,返回響應給瀏覽器
  4. 瀏覽器接收到響應後渲染頁面

20. 什麼是cdn

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

數據庫和框架篇

21. 列舉常見的數據庫

關係型數據庫:MySQL,Oracle,SQLServer,SQLite,DB2

非關係型數據庫:MongoDB,Redis,HBase,Neo4j

22. 數據庫設計三大範式

創建科學的,規範的的數據庫是須要知足一些規範的,以此來優化數據數據存儲方式,在關係型數據庫中這些規範就能夠稱爲範式。

第一範式:當關系模式 R 的全部屬性都不能在分解爲更基本的數據單位時,稱 R 是知足第一範式的,簡記爲 1NF。

關係模式R的全部屬性不能再分解

第二範式:若是關係模式 R 知足第一範式,而且 R 的全部非主屬性都徹底依賴於 R 的每個候選關鍵屬性,稱 R 知足第二範式,簡記爲 2NF。

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

三範式:設 R 是一個知足第一範式條件的關係模式,X 是 R 的任意屬性集,若是 X 非傳遞依賴於 R 的任意一個候選關鍵字,稱 R 知足第三範式,簡記爲 3NF。

數據不能存在傳遞關係,即每一個屬性都跟主鍵有直接關係而不是間接關係

23. 什麼是數據庫事務

事務(Transaction)是併發控制的基本單位。所謂的事務,它是一個操做序列,這些操做要麼都執行,要麼都不執行,它是一個不可分割的工做單位。

在關係數據庫中,一個事務能夠是一條 SQL 語句、一組 SQL 語句或整個程序。

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

24. MySQL 索引種類

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

  1. 普通索引
  2. 惟一索引
  3. 主鍵索引
  4. 組合索引
  5. 全文索引

25. 數據庫設計中一對多和多對多的應用場景

一對一關係示例: 一個學生對應一個學生檔案材料,或者每一個人都有惟一的身份證編號。

一對多關係示例: 一個學生只屬於一個班,可是一個班級有多名學生。

多對多關係示例: 一個學生能夠選擇多門課,一門課也有多名學生。

26. 簡述觸發器、函數、視圖、存儲過程

觸發器:觸發器是一個特殊的存儲過程,它是數據庫在 insert、update、delete 的時候自動執行的代碼塊。

函數:數據庫中提供了許多內置函數,還能夠自定義函數,實現 sql 邏輯。

視圖:視圖是由查詢結果造成的一張虛擬表,是表經過某種運算獲得的一個投影。

存儲過程:把一段代碼封裝起來,當要執行這一段代碼的時候,能夠經過調用該存儲過程來實現(通過第一次編譯後再次調用不須要再次編譯,比一個個執行 sql 語句效率高)

27. 經常使用 SQL 語句

DML(數據操做語言)

  • SELECT - 從數據庫表中獲取數據
  • UPDATE - 更新數據庫表中的數據
  • DELETE - 從數據庫表中刪除數據
  • INSERT INTO - 向數據庫表中插入數據

DDL(數據定義語言)

  • CREATE DATABASE - 建立新數據庫
  • ALTER DATABASE - 修改數據庫
  • CREATE TABLE - 建立新表
  • ALTER TABLE - 變動(改變)數據庫表
  • DROP TABLE - 刪除表
  • CREATE INDEX - 建立索引(搜索鍵)
  • DROP INDEX - 刪除索引

28. 主鍵和外鍵的區別

定義主鍵和外鍵主要是爲了維護關係數據庫的完整性

主鍵是能肯定一條記錄的惟一標識。不能重複,不容許爲空。

外鍵用於與另外一張表關聯。是能肯定另外一張表記錄的字段,用於保持數據的一致性。

主鍵 外鍵 索引
定義 惟一標識一條記錄,不能重複,不容許爲空 表的外鍵是另外一表的主鍵,外鍵能夠重複,能夠是空值 該字段沒有重複值,但能夠有空值
做用 用來保證數據完整性 用來和其餘表創建聯繫 提升查詢排序的速度
個數 只能有一個 可有多個 可有多個

29. 如何開啓 MySQL 慢日誌查詢

  1. 修改配置文件,而後重啓服務生效 在linux下,vim /etc/my.cnf,在[mysqld]內容項下增長: slow_query_log = ON long_query_time = 2 # 查詢超過2秒的就會記錄
  2. 命令行,可是重啓服務後會失效 SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 2;

30. MySQL 數據庫備份命令

mysqldump -u 用戶名 -p 數據庫名 > 導出的文件名

31. char 和 varchar 的區別

char:存儲定長數據很方便,CHAR 字段上的索引效率級高,必須在括號裏定義長度,能夠有默認值,好比定義 char(10)。

varchar:存儲變長數據,但存儲效率沒有 CHAR 高,必須在括號裏定義長度,能夠有默認值。

32. 最左前綴原則

mysql 創建多列索引(聯合索引)有最左前綴的原則,即最左優先,如:

若是有一個2列的索引(col1,col2),則已經對(col1)、(col1,col2)上創建了索引;

若是有一個3列索引(col1,col2,col3),則已經對(col1)、(col1,col2)、(col1,col2,col3)上創建了索引;

33. 沒法命中索引的狀況

  1. 使用or關鍵字會致使沒法命中索引
  2. 左前導查詢會致使沒法命中索引,如 like '%a' 或者 like '%a%'
  3. 單列索引的索引列爲 null 時全值匹配會使索引失效,組合索引全爲 null 時索引失效
  4. 組合索引不符合左前綴原則的列沒法命中索引,如咱們有4個列 a、b、c、d,咱們建立一個組合索引 INDEX(a,b,c,d),那麼能命中索引的查詢爲 a,ab,abc,abcd,除此以外都沒法命中索引
  5. 強制類型轉換會致使索引失效
  6. 負向查詢條件會致使沒法使用索引,好比 NOT IN,NOT LIKE,!= 等
  7. 若是 mysql 估計使用全表掃描要比使用索引快,則不使用索引

34. 數據庫讀寫分離

讀寫分離,就是將數據庫分爲了主從庫,一個主庫用於寫數據,多個從庫完成讀數據的操做,主從庫之間經過某種機制進行數據的同步,是一種常見的數據庫架構。

35. 數據庫分庫分表

數據庫水平切分,是一種常見的數據庫架構,是一種經過算法,將數據庫進行分割的架構。一個水平切分集羣中的每一個數據庫,一般稱爲一個「分片」。每個分片中的數據沒有重合,全部分片中的數據並集組成所有數據。

水平切分分爲庫內分表和分庫分表,是根據表內數據內在的邏輯關係,將同一個表按不一樣的條件分散到多個數據庫或多個表中,每一個表中只包含一部分數據,從而使得單個表的數據量變小,達到分佈式的效果。

36. redis 和 memcached 比較

  • redis 和 memcached 都是將數據存放在內存中,都是內存數據庫。不過 memcached 還可用於緩存其餘東西,例如圖片、視頻等等。
  • redis 不只僅支持簡單的 k/v 類型的數據,同時還提供 list,set,hash 等數據結構的存儲。
  • 分佈式設定, 均可以作一主多從或一主一從 。
  • 存儲數據安全,memcached 掛掉後,數據徹底丟失;redis 能夠按期保存到磁盤(持久化)。
  • 災難恢復,memcached 掛掉後,數據不可恢復; redis 數據丟失後能夠經過 aof 恢復。

37. redis中數據庫默認是多少個 db 及做用

redis 默認有16個數據庫,每一個數據庫中的數據都是隔離的,這樣,在存儲數據的時候,就能夠指定把不一樣的數據存儲到不一樣的數據庫中。 且只有單機纔有,若是是集羣就沒有數據庫的概念。

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

RDB 持久化:是將 Reids 在內存中的數據庫記錄定時 dump 到磁盤上的持久化

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

39. redis 支持的過時策略

通用的三種過時策略

  1. 定時刪除 在設置 key 的過時時間的同時,爲該 key 建立一個定時器,讓定時器在 key 的過時時間來臨時,對 key 進行刪除
  2. 惰性刪除 key 過時的時候不刪除,每次從數據庫獲取 key 的時候去檢查是否過時,若過時,則刪除,返回 null。
  3. 按期刪除 每隔一段時間執行一次刪除過時 key 操做

redis 採用惰性刪除+按期刪除策略

40. 如何保證 redis 中的數據都是熱點數據

限定 Redis 佔用的內存,Redis 會根據自身數據淘汰策略,加載熱數據到內存。 因此,計算一下全部熱點數據大約佔用的內存,而後設置一下 Redis 內存限制便可。

41. Python 操做 redis

使用 redis 第三方庫來操做

import redis

# 建立一個 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
複製代碼

42. 基於 redis 實現發佈和訂閱

訂閱者

if __name__ == "__main__":
    conn = redis.Redis(host='',
                       port=12143, password='')

    ps = conn.pubsub()
    ps.subscribe('chat')  # 從 chat 訂閱消息
    for item in ps.listen():  # 監聽狀態:有消息發佈了就拿過來
        if item['type'] == 'message':
            print(item)
            print(item['channel'])
            print(item['data'])
複製代碼

發佈者

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 i in range(len(number_list)):
        value_new = str(number_list[i]) + ' ' + str(signal[i])
        print(value_new)
        r.publish("chat", value_new)
複製代碼

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

import redis
con = redis.Redis()
con.keys(pattern='key*') # *表明通配符
複製代碼

44. 基於 redis 實現先進先出、後進先出及優先級隊列

class Zhan:
    def __init__(self,conn):
        self.conn = conn
    def push(self,val):
        self.conn.rpush('aaa',val)
    def pop(self):
        return self.conn.rpop('aaa')
 
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
複製代碼

45. redis 如何實現主從複製

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

46. 循環獲取 redis 中某個很是大的列表數據

def list_iter(name):
    """ 自定義redis列表增量迭代 :param name: redis中的name,即:迭代name對應的列表 :return: yield 返回 列表元素 """
    list_count = r.llen(name)
    for index in xrange(list_count):
        yield r.lindex(name, index)
複製代碼

47. redis 中的 watch 的命令的做用

watch 用於在進行事務操做的最後一步也就是在執行 exec 以前對某個 key 進行監視,若是這個被監視的 key 被改動,那麼事務就被取消,不然事務正常執行。

48. redis 分佈式鎖

爲 redis 集羣設計的鎖,防止多個任務同時修改數據庫,其本質就是爲集羣中的每一個主機設置一個會超時的字符串,當集羣中有一半多的機器設置成功後就認爲加鎖成功,直至鎖過時或解鎖不會有第二個任務加鎖成功。

49. http 協議

超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最爲普遍的一種網絡協議。HTTP 是一個客戶端和服務器端請求和應答的標準。客戶端是終端用戶,服務器端是網站。通常由 HTTP 客戶端發起一個請求,創建一個到服務器指定端口(默認是80端口)的 TCP 鏈接,HTTP 服務器則在那個端口監聽客戶端發送過來的請求,並給與響應。

50. uwsgi,uWSGI 和 WSGI 的區別

WSGI:全稱是 Web Server Gateway Interface,是一種描述 web server 如何與 web application 通訊的規範。django,flask 等都遵循該協議。

uwsgi:是服務器和服務端應用程序的一種協議,規定了怎麼把請求轉發給應用程序和返回; uwsgi 是一種線路協議而不是通訊協議,在此經常使用於在 uWSGI 服務器與其餘網絡服務器的數據通訊。

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

51. HTTP 狀態碼

1xx: 信息

2xx:成功

3xx:重定向

4xx:客戶端錯誤

5xx:服務器錯誤

52. HTTP常見請求方式

GET,POST,PUT,DELETE,PATCH 等

53. 響應式佈局

響應式佈局是 Ethan Marcotte 在2010年5月份提出的一個概念,簡而言之,就是一個網站可以兼容多個終端——而不是爲每一個終端作一個特定的版本。

54. 實現一個簡單的 AJAX 請求

AJAX 是一種在無需從新加載整個網頁的狀況下,可以更新部分網頁的技術。

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裏面的全部內容
                         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);
                      }
         });
    });
});
複製代碼

55. 同源策略

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

若是兩個頁面的協議,端口(若是有指定)和主機都相同,則兩個頁面具備相同的源。咱們也能夠把它稱爲「協議/主機/端口 tuple」,或簡單地叫作「tuple". ("tuple" ,「元」,是指一些事物組合在一塊兒造成一個總體,好比(1,2)叫二元,(1,2,3)叫三元)

56. 什麼是 CORS

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

57. 什麼是 CSRF

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

58. 前端實現輪詢、長輪詢

輪詢

var xhr = new XMLHttpRequest();
    setInterval(function(){
        xhr.open('GET','/user');
        xhr.onreadystatechange = function(){

        };
        xhr.send();
    },1000)
複製代碼

長輪詢

function ajax(){
        var xhr = new XMLHttpRequest();
        xhr.open('GET','/user');
        xhr.onreadystatechange = function(){
              ajax();
        };
        xhr.send();
    }
複製代碼

59. 簡述 MVC 和 MTV

所謂 MVC 就是把 web 應用分爲模型(M),控制器(C),視圖(V)三層,他們之間以一種插件似的,鬆耦合的方式鏈接在一塊兒。 模型負責業務對象與數據庫的對象(ORM),視圖負責與用戶的交互(頁面),控制器(C)接受用戶的輸入調用模型和視圖完成用戶的請求。

Django 中的 MTV 模式:Model(模型):負責業務對象與數據庫的對象(ORM),Template(模版):負責如何把頁面展現給用戶,View(視圖):負責業務邏輯,並在適當的時候調用 Model 和 Template,本質上與 MVC 相同。

60. 接口的冪等性

接口冪等性就是用戶對於同一操做發起的一次請求或者屢次請求的結果是一致的,不會由於屢次點擊而產生了反作用。

61. Flask 框架的優點

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

62. 什麼是 ORM

ORM 的全稱是 Object Relational Mapping,即對象關係映射。它的實現思想就是將關係數據庫中表的數據映射成爲對象,以對象的形式展示,這樣開發人員就能夠把對數據庫的操做轉化爲對這些對象的操做。

63. PV、UV 的含義

PV:是(page view)訪問量,頁面瀏覽量或點擊量,衡量網站用戶訪問的網頁數量。在必定統計週期內用戶每打開或刷新一個頁面就記錄1次,屢次打開或刷新同一頁面則瀏覽量累計。 UV:是(Unique Visitor)獨立訪客,統計一段時間內訪問某站點的用戶數(以cookie爲依據)。

64. supervisor 的做用

supervisor 管理進程,是經過 fork/exec 的方式將這些被管理的進程看成 supervisor 的子進程來啓動,因此咱們只須要將要管理進程的可執行文件的路徑添加到 supervisor 的配置文件中便可。

65. 使用 ORM 和原生 SQL 的優缺點

優勢:

  • 方便的使用面向對象,語句清晰;
  • 有效的防止 SQL 注入;
  • 方便動態構造語句,對於不一樣的表的相同操做採用多態實現更優雅;
  • 必定程度上方便重構數據層
  • 方便設置設置鉤子函數

缺點:

  • 不太容易處理複雜查詢語句
  • 性能較直接用 SQL 差

66. 列舉一些 django 的內置組件

  • Admin 組件:是對 model 中對應的數據表進行增刪改查提供的組件
  • model 組件:負責操做數據庫
  • form 組件:生成 HTML 代碼;數據有效性校驗;校驗信息返回並展現
  • ModelForm 組件:用於數據庫操做,也可用於用戶請求的驗證

67. 列舉 Django 中執行原生 sql 的方法

  1. 使用 execute 執行自定義的 SQL 直接執行 SQL 語句(相似於 pymysql 的用法)
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT DATE_FORMAT(create_time, '%Y-%m') FROM blog_article;")
ret = cursor.fetchall()
print(ret)
複製代碼
  1. 使用 extra 方法:queryset.extra(select={"key": "原生的SQL語句"})
  2. 使用 raw 方法
    1. 執行原始 sql 並返回模型
    2. 依賴於 model 模型,多用於查詢操做

68. cookie 和 session 的區別

cookie 是保存在瀏覽器端的鍵值對,能夠用來作用戶認證。

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

69. beautifulsoup 模塊的做用

BeautifulSoup 庫是解析、遍歷、維護「標籤樹」的功能庫。

url = "http://www.baidu.com/"
request = requests.get(url)
html = request.content
soup = BeautifulSoup(html, "html.parser", from_encoding="utf-8")
複製代碼

70. Selenium 模塊簡述

Selenium 是模擬操做瀏覽器的庫,能夠根據咱們的指令,讓瀏覽器自動加載頁面,獲取須要的數據,甚至頁面截屏,或者判斷網站上某些動做是否發生等。

from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
print(browser.page_source) # browser.page_source 是獲取網頁的所有 html
browser.close()
複製代碼

歡迎關注個人微信公衆號--蘿蔔大雜燴,或者掃描下方的二維碼,你們一塊兒交流,學習和進步!

相關文章
相關標籤/搜索