主頁 > 後端開發 > Redis 常見問題

Redis 常見問題

2022-11-20 06:29:16 後端開發

Redis 常見問題

      落葉他鄉樹,寒燈獨夜人,

一、 什么是Redis?

  • Redis 是一個使用 C 語言寫成的,開源的高性能key-value非關系快取資料庫;
  • Redis的資料都基于快取的,所以很快,每秒可以處理超過 10萬次讀寫操作;
  • Redis也可以實作資料寫入磁盤中,保證了資料的安全不丟失,而且Redis的操作是原子性的,

二、 Redis有哪些優缺點?

優點

  1. 讀寫性能優異, Redis能讀的速度是110000次/s,寫的速度是81000次/s,
  2. 支持資料持久化,支持AOF和RDB兩種持久化方式,
  3. 支持事務,Redis的所有操作都是原子性的,同時Redis還支持對幾個操作合并后的原子性執行,
  4. 資料結構豐富,除了支持string型別的value外還支持hash、set、zset、list等資料結構,
  5. 支持主從復制,主機 會自動將資料同步到 從機,可以進行讀寫分離,
  6. 豐富的特性:可用于快取,訊息,按key設定過期時間,過期后將會自動洗掉,

缺點

  1. 資料庫容量受到物理記憶體的限制,不能用作海量資料的高性能讀寫,因此Redis適合的場景主要局限在較小資料量的高性能操作和運算上,
  2. Redis 不具備自動容錯和恢復功能,主機從機的宕機都會導致前端部分讀寫請求失敗,需要等待機器重啟或者手動切換前端的IP才能恢復,
  3. 主機宕機,宕機前有部分資料未能及時同步到從機,切換IP后還會引入資料不一致的問題,降低了系統的可用性,
  4. Redis 較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜,為避免這一問題,運維人員在系統上線時必須確保有足夠的空間,這對資源造成了很大的浪費,

三、使用redis有哪些好處?

  • (1) 速度快,因為資料存在記憶體中,類似于HashMap,HashMap的優勢就是查找和操作的時間復雜度都很低
  • (2) 支持豐富資料型別,支持string,list,set,sorted set,hash
  • (3) 支持事務,操作都是原子性,所謂的原子性就是對資料的更改要么全部執行,要么全部不執行
  • (4) 豐富的特性:可用于快取,訊息,按key設定過期時間,過期后將會自動洗掉

四、 為什么要用 Redis ?為什么要用快取?

主要從“高性能”和“高并發”這兩點來看待這個問題,

高性能

假如用戶第一次訪問資料庫中的某些資料,這個程序會比較慢,因為是從硬碟上讀取的,將該用戶訪問的資料存在數快取中,這樣下一次再訪問這些資料的時候就可以直接從快取中獲取了,操作快取就是直接操作記憶體,所以速度相當快,如果資料庫中的對應資料改變的之后,同步改變快取中相應的資料即可!

高并發

直接操作快取能夠承受的請求是遠遠大于直接訪問資料庫的,所以我們可以考慮把資料庫中的部分資料轉移到快取中去,這樣用戶的一部分請求會直接到快取這里而不用經過資料庫,

五、為什么要用 Redis 而不用 map/guava 做快取?

  • 快取分為本地快取和分布式快取,以 Java 為例,使用自帶的 map 或者 guava 實作的是本地快取,最主要的特點是輕量以及快速,生命周期隨著 jvm 的銷毀而結束,并且在多實體的情況下,每個實體都需要各自保存一份快取,快取不具有一致性,
  • 使用 redis 或 memcached 之類的稱為分布式快取,在多實體的情況下,各實體共用一份快取資料,快取具有一致性,缺點是需要保持 redis 或 memcached服務的高可用,整個程式架構上較為復雜,

六、Redis為什么這么快?

  • 1、完全基于記憶體,絕大部分請求是純粹的記憶體操作,非常快速,資料存在記憶體中,類似于HashMap,HashMap 的優勢就是查找和操作的時間復雜度都是O(1);
  • 2、資料結構簡單,對資料操作也簡單,Redis 中的資料結構是專門進行設計的;
  • 3、采用單執行緒,避免了不必要的背景關系切換和競爭條件,也不存在多行程或者多執行緒導致的切換
  • 而消耗 CPU,不用去考慮各種鎖的問題(單執行緒不存在多個執行緒同時訪問同一資源),不存在加鎖釋放鎖操作,沒有因為可能出現死鎖而導致的性能消耗;
  • 4、使用多路 I/O 復用模型,非阻塞 IO;
  • 5、使用底層模型不同,它們之間底層實作方式以及與客戶端之間通信的應用協議不一樣,Redis直接自己構建了 VM 機制 ,因為一般的系統呼叫系統函式的話,會浪費一定的時間去移動和請求;

七、Redis有哪些資料型別?

Redis除了最常用的5種基本資料型別,包括String,List,Set,Zset,Hash,還有geospatial、hyperloglog和bitmap 三種特殊資料型別,https://www.cnblogs.com/taojietaoge/p/15915947.html(Redis資料型別)

八、 Redis的應用場景

計數器

可以對 String 進行自增自減運算,從而實作計數器功能,Redis 這種記憶體型資料庫的讀寫性能非常高,很適合存盤頻繁讀寫的計數量,

快取

將熱點資料放到記憶體中,設定記憶體的最大使用量以及淘汰策略來保證快取的命中率,

會話快取

可以使用 Redis 來統一存盤多臺應用服務器的會話資訊,當應用服務器不再存盤用戶的會話資訊,也就不再具有狀態,一個用戶可以請求任意一個應用服務器,從而更容易實作高可用性以及可伸縮性,

全頁快取(FPC)

除基本的會話token之外,Redis還提供很簡便的FPC平臺,以Magento為例,Magento提供一個插件來使用Redis作為全頁快取后端,此外,對WordPress的用戶來說,Pantheon有一個非常好的插件 wpredis,這個插件能幫助你以最快速度加載你曾瀏覽過的頁面,

查找表

例如 DNS 記錄就很適合使用 Redis 進行存盤,查找表和快取類似,也是利用了 Redis 快速的查找特性,但是查找表的內容不能失效,而快取的內容可以失效,因為快取不作為可靠的資料來源,

訊息佇列(發布/訂閱功能)

List 是一個雙向鏈表,可以通過 lpush 和 rpop 寫入和讀取訊息,不過最好使用 Kafka、RabbitMQ 等訊息中間件,

分布式鎖實作

在分布式場景下,無法使用單機環境下的鎖來對多個節點上的行程進行同步,可以使用 Redis 自帶的 SETNX 命令實作分布式鎖,除此之外,還可以使用官方提供的RedLock 分布式鎖實作,

其它

Set 可以實作交集、并集等操作,從而實作共同好友等功能,ZSet 可以實作有序性操作,從而實作排行榜等功能,

九、什么是Redis持久化?

持久化就是把記憶體的資料寫到磁盤中去,防止服務宕機導致記憶體資料丟失,

十、 Redis 的持久化機制是什么?各自的優缺點?

Redis 提供兩種持久化機制 RDB(默認) 和 AOF 機制,

RDB

  • RDB是Redis DataBase縮寫快照,
  • RDB是Redis默認的持久化方式,按照一定的時間將記憶體的資料以快照的形式保存到硬碟中,對應產生的資料檔案為dump.rdb,通過組態檔中的save引數來定義快照的周期,

優點

  • 1、只有一個檔案 dump.rdb,方便持久化,
  • 2、容災性好,一個檔案可以保存到安全的磁盤,
  • 3、性能最大化,fork 子行程來完成寫操作,讓主行程繼續處理命令,所以是 IO 最大化,使用單獨子行程來進行持久化,主行程不會進行任何 IO 操作,保證了 redis 的高性能,
  • 4.相對于資料集大時,比 AOF 的啟動效率更高,

缺點

  • 1、資料安全性低,RDB 是間隔一段時間進行持久化,如果持久化之間 redis 發生故障,會發生資料丟失,所以這種方式更適合資料要求不嚴謹的時候),
  • 2、AOF(Append-only file)持久化方式: 是指所有的命令列記錄以 redis 命令請 求協議的格式完全持久化存盤)保存為 aof 檔案,

AOF

  • AOF持久化(即Append Only File持久化),則是將Redis執行的每次寫命令記錄到單獨的日志檔案中,當重啟Redis會重新將持久化的日志中檔案恢復資料,
  • 當兩種方式同時開啟時,資料恢復Redis會優先選擇AOF恢復,
優點
  • 1、資料安全,aof 持久化可以配置 appendfsync 屬性,有 always,每進行一次 命令操作就記錄到 aof 檔案中一次,
  • 2、通過 append 模式寫檔案,即使中途服務器宕機,可以通過 redis-check-aof 工具解決資料一致性問題,
  • 3、AOF 機制的 rewrite 模式,AOF 檔案沒被 rewrite 之前(檔案過大時會對命令 進行合并重寫),可以洗掉其中的某些命令(比如誤操作的 flushall)),
缺點
  • 1、AOF 檔案比 RDB 檔案大,且恢復速度慢,
  • 2、資料集大的時候,比 rdb 啟動效率低,

倆種持久化的優缺點是什么?

  • AOF檔案比RDB更新頻率高,優先使用AOF還原資料,
  • AOF比RDB更安全也更大,
  • RDB性能比AOF好,
  • 如果兩個都配了優先加載AOF,

十一、如何選擇合適的持久化方式?

  • 一般來說,如果想達到足以媲美PostgreSQL的資料安全性,你應該同時使用兩種持久化功能,在這種情況下,當 Redis 重啟的時候會優先載入AOF檔案來恢復原始的資料,因為在通常情況下AOF檔案保存的資料集要比RDB檔案保存的資料集要完整,如果你非常關心你的資料,但仍然可以承受數分鐘以內的資料丟失,那么你可以只使用RDB持久化,
  • 有很多用戶都只使用AOF持久化,但并不推薦這種方式,因為定時生成RDB快照(snapshot)非常便于進行資料庫備份,并且 RDB 恢復資料集的速度也要比AOF恢復的速度要快,除此之外,使用RDB還可以避免AOF程式的bug,
  • 如果你只希望你的資料在服務器運行的時候存在,你也可以不使用任何持久化方式,

Redis持久化資料和快取怎么做擴容?

  • 如果Redis被當做快取使用,使用一致性哈希實作動態擴容縮容,
  • 如果Redis被當做一個持久化存盤使用,必須使用固定的keys-to-nodes映射關系,節點的數量一旦確定不能變化,否則的話(即Redis節點需要動態變化的情況),必須使用可以在運行時進行資料再平衡的一套系統,而當前只有Redis集群可以做到這樣,

十二、Redis的過期鍵的洗掉策略

過期策略通常有以下三種:定時過期、惰性過期和定期過期,

定時過期

  • 每個設定過期時間的key都需要創建一個定時器,到過期時間就會立即清除,該策略可以立即清除過期的資料,對記憶體很友好;
  • 但是會占用大量的CPU資源去處理過期的資料,從而影響快取的回應時間和吞吐量,

惰性過期

  • 只有當訪問一個key時,才會判斷該key是否已過期,過期則清除,該策略可以最大化地節省CPU資源,卻對記憶體非常不友好,
  • 極端情況可能出現大量的過期key沒有再次被訪問,從而不會被清除,占用大量記憶體,

定期過期

  • 每隔一定的時間,會掃描一定數量的資料庫的expires字典中一定數量的key,并清除其中已過期的key,
  • 該策略是前兩者的一個折中方案,通過調整定時掃描的時間間隔和每次掃描的限定耗時,可以在不同情況下使得CPU和記憶體資源達到最優的平衡效果, (expires字典會保存所有設定了過期時間的key的過期時間資料,其中,key是指向鍵空間中的某個鍵的指標,value是該鍵的毫秒精度的UNIX時間戳表示的過期時間,鍵空間是指該Redis集群中保存的所有鍵,)
  • Redis中同時使用了惰性過期和定期過期兩種過期策略,

十三、Redis key的過期時間和永久有效分別怎么設定?

通過 expire 和 persist 命令,

十四、我們知道通過expire來設定key 的過期時間,那么對過期的資料怎么處理呢?

除了快取服務器自帶的快取失效策略之外(Redis默認的有6中策略可供選擇),我們還可以根據具體的業務需求進行自定義的快取淘汰,常見的策略有兩種:
  • 1、定時去清理過期的快取;
  • 2、當有用戶請求過來時,再判斷這個請求所用到的快取是否過期,過期的話就去底層系統得到新資料并更新快取,
兩者各有優劣,第一種的缺點是維護大量快取的key是比較麻煩的,第二種的缺點就是每次用戶請求過來都要判斷快取失效,邏輯相對比較復雜!具體用哪種方案,大家可以根據自己的應用場景來權衡,

十五、MySQL里有2000w資料,redis中只存20w的資料,如何保證redis中的資料都是熱點資料?

redis記憶體資料集大小上升到一定大小的時候,就會施行資料淘汰策略,

十六、Redis的記憶體淘汰策略有哪些?

Redis的記憶體淘汰策略是指在Redis的用于快取的記憶體不足時,怎么處理需要新寫入且需要申請額外空間的資料,

全域的鍵空間選擇性移除

  • noeviction:當記憶體不足以容納新寫入資料時,新寫入操作會報錯,
  • allkeys-lru:當記憶體不足以容納新寫入資料時,在鍵空間中,移除最近最少使用的key,(這個是最常用的)
  • allkeys-random:當記憶體不足以容納新寫入資料時,在鍵空間中,隨機移除某個key,

設定過期時間的鍵空間選擇性移除

  • volatile-lru:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,移除最近最少使用的key,
  • volatile-random:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,隨機移除某個key,
  • volatile-ttl:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,有更早過期時間的key優先移除,
總結
Redis的記憶體淘汰策略的選取并不會影響過期的key的處理,記憶體淘汰策略用于處理記憶體不足時的需要申請額外空間的資料;過期策略用于處理過期的快取資料,

十七、Redis主要消耗什么物理資源?

記憶體,

十八、Redis的記憶體用完了會發生什么?

如果達到設定的上限,Redis的寫命令會回傳錯誤資訊(但是讀命令還可以正常回傳,)或者可以配置記憶體淘汰機制,當Redis達到記憶體上限時會沖刷掉舊的內容,

十九、Redis如何做記憶體優化?

  • 可以好好利用Hash、list、sorted set、set等集合型別資料,因為通常情況下很多小的Key-Value可以用更緊湊的方式存放到一起,
  • 盡可能使用散串列(hashes),散串列(是說散串列里面存盤的數少)使用的記憶體非常小,所以你應該盡可能的將你的資料模型抽象到一個散串列里面,
  • 比如你的web系統中有一個用戶物件,不要為這個用戶的名稱,姓氏,郵箱,密碼設定單獨的key,而是應該把這個用戶的所有資訊存盤到一張散串列里面,

二十、Redis執行緒模型

  • Redis基于Reactor模式開發了網路事件處理器,這個處理器被稱為檔案事件處理器(file event handler),它的組成結構為4部分:多個套接字、IO多路復用程式、檔案事件分派器、事件處理器,
  • 因為檔案事件分派器佇列的消費是單執行緒的,所以Redis才叫單執行緒模型,
  • 檔案事件處理器使用 I/O 多路復用(multiplexing)程式來同時監聽多個套接字,并根據套接字目前執行的任務來為套接字關聯不同的事件處理器,
  • 當被監聽的套接字準備好執行連接應答(accept)、讀取(read)、寫入(write)、關閉(close)等操作時,與操作相對應的檔案事件就會產生, 這時檔案事件處理器就會呼叫套接字之前關聯好的事件處理器來處理這些事件,
  • 雖然檔案事件處理器以單執行緒方式運行,但通過使用 I/O 多路復用程式來監聽多個套接字,檔案事件處理器既實作了高性能的網路通信模型,又可以很好地與 redis 服務器中其他同樣以單執行緒方式運行的模塊進行對接,這保持了 Redis 內部單執行緒設計的簡單性,

二十一、什么是事務?

  • 事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行,事務在執行的程序中,不會被其他客戶端發送來的命令請求所打斷,
  • 事務是一個原子操作:事務中的命令要么全部被執行,要么全部都不執行,

二十二、Redis事務的概念

  • Redis 事務的本質是通過MULTI、EXEC、WATCH等一組命令的集合,事務支持一次執行多個命令,一個事務中所有命令都會被序列化,
  • 在事務執行程序,會按照順序串行化執行佇列中的命令,其他客戶端提交的命令請求不會插入到事務執行命令序列中,
  • 總結說:redis事務就是一次性、順序性、排他性的執行一個佇列中的一系列命令,

二十三、Redis事務的三個階段

  • 1. 事務開始 MULTI
  • 2. 命令入隊
  • 3. 事務執行 EXEC
事務執行程序中,如果服務端收到有EXEC、DISCARD、WATCH、MULTI之外的請求,將會把請求放入佇列中排隊,

二十四、Redis事務相關命令

Redis事務功能是通過MULTI、EXEC、DISCARD和WATCH 四個原語實作的,Redis會將一個事務中的所有命令序列化,然后按順序執行,
  • 1. redis 不支持回滾,“Redis 在事務失敗時不進行回滾,而是繼續執行余下的命令”, 所以 Redis 的內部可以保持簡單且快速,
  • 2. 如果在一個事務中的命令出現錯誤,那么所有的命令都不會執行;
  • 3. 如果在一個事務中出現運行錯誤,那么正確的命令會被執行,
  • WATCH:命令是一個樂觀鎖,可以為 Redis 事務提供 check-and-set (CAS)行為, 可以監控一個或多個鍵,一旦其中有一個鍵被修改(或洗掉),之后的事務就不會執行,監控一直持續到EXEC命令,
  • MULTI:命令用于開啟一個事務,它總是回傳OK, MULTI執行之后,客戶端可以繼續向服務器發送任意多條命令,這些命令不會立即被執行,而是被放到一個佇列中,當EXEC:命令被呼叫時,所有佇列中的命令才會被執行,
  • EXEC:執行所有事務塊內的命令,回傳事務塊內所有命令的回傳值,按命令執行的先后順序排列,當操作被打斷時,回傳空值 nil ,
  • DISCARD:通過呼叫DISCARD,客戶端可以清空事務佇列,并放棄執行事務, 并且客戶端會從事務狀態中退出,
  • UNWATCH:命令可以取消watch對所有key的監控,

二十五、事務管理(ACID)概述

原子性(Atomicity)
原子性是指事務是一個不可分割的作業單位,事務中的操作要么都發生,要么都不發生,
一致性(Consistency)
事務前后資料的完整性必須保持一致,
隔離性(Isolation)
多個事務并發執行時,一個事務的執行不應影響其他事務的執行,
持久性(Durability)
持久性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響,
Redis的事務總是具有ACID中的一致性和隔離性,其他特性是不支持的,當服務器運行在_AOF_持久化模式下,并且appendfsync選項的值為always時,事務也具有持久性,

二十六、Redis事務支持隔離性嗎

Redis 是單行程程式,并且它保證在執行事務時,不會對事務進行中斷,事務可以運行直到執行完所有事務佇列中的命令為止,因此,Redis 的事務是總是帶有隔離性的,

二十七、Redis事務保證原子性嗎,支持回滾嗎

Redis中,單條命令是原子性執行的,但事務不保證原子性,且沒有回滾,事務中任意命令執行失敗,其余的命令仍會被執行,

二十八、Redis事務其他實作

  • 基于Lua腳本,Redis可以保證腳本內的命令一次性、按順序地執行,其同時也不提供事務運行錯誤的回滾,執行程序中如果部分命令運行錯誤,剩下的命令還是會繼續運行完,
  • 基于中間標記變數,通過另外的標記變數來標識事務是否執行完成,讀取資料時先讀取該標記變數判斷是否事務執行完成,但這樣會需要額外寫代碼實作,比較繁瑣,

二十九、集群方案-哨兵模式

哨兵的介紹
sentinel,中文名是哨兵,哨兵是 redis 集群機構中非常重要的一個組件,主要有以下功能:
  • 集群監控:負責監控 redis master 和 slave 行程是否正常作業,
  • 訊息通知:如果某個 redis 實體有故障,那么哨兵負責發送訊息作為報警通知給管理員,
  • 故障轉移:如果 master node 掛掉了,會自動轉移到 slave node 上,
  • 配置中心:如果故障轉移發生了,通知 client 客戶端新的 master 地址,
哨兵用于實作 redis 集群的高可用,本身也是分布式的,作為一個哨兵集群去運行,互相協同作業,
故障轉移時,判斷一個 master node 是否宕機了,需要大部分的哨兵都同意才行,涉及到了分布式選舉的問題,
即使部分哨兵節點掛掉了,哨兵集群還是能正常作業的,因為如果一個作為高可用機制重要組成部分的故障轉移系統本身是單點的,那就很坑爹了,
哨兵的核心知識
  • 哨兵至少需要 3 個實體,來保證自己的健壯性,
  • 哨兵 + redis 主從的部署架構,是不保證資料零丟失的,只能保證 redis 集群的高可用性,
  • 對于哨兵 + redis 主從這種復雜的部署架構,盡量在測驗環境和生產環境,都進行充足的測驗和演練,

三十、集群方案- 官方Redis Cluster 方案(服務端路由查詢)

redis 集群模式的作業原理能說一下么?在集群模式下,redis 的 key 是如何尋址的?分布式尋址都有哪些演算法?了解一致性 hash 演算法嗎?
簡介
Redis Cluster是一種服務端Sharding技術,3.0版本開始正式提供,Redis Cluster并沒有使用一致性hash,而是采用slot(槽)的概念,一共分成16384個槽,將請求發送到任意節點,接收到請求的節點會將查詢請求發送到正確的節點上執行,
方案說明
  • 1. 通過哈希的方式,將資料分片,每個節點均分存盤一定哈希槽(哈希值)區間的資料,默認分配了16384 個槽位
  • 2. 每份資料分片會存盤在多個互為主從的多節點上
  • 3. 資料寫入先寫主節點,再同步到從節點(支持配置為阻塞同步)
  • 4. 同一分片多個節點間的資料不保持一致性
  • 5. 讀取資料時,當客戶端操作的key沒有分配在該節點上時,redis會回傳轉向指令,指向正確的節點
  • 6. 擴容時時需要需要把舊節點的資料遷移一部分到新節點
在 redis cluster 架構下,每個 redis 要放開兩個埠號,比如一個是 6379,另外一個就是 加1w的埠號,比如 16379,16379 埠號是用來進行節點間通信的,也就是 cluster bus 的東西,cluster bus 的通信,用來進行故障檢測、配置更新、故障轉移授權,cluster bus 用了另外一種二進制的協議,gossip 協議,用于節點間進行高效的資料交換,占用更少的網路帶寬和處理時間,
節點間的內部通信機制
基本通信原理
集群元資料的維護有兩種方式:集中式、Gossip 協議,redis cluster 節點間采用 gossip 協議進行通信,
  • 分布式尋址演算法
  • hash 演算法(大量快取重建)
  • 一致性 hash 演算法(自動快取遷移)+ 虛擬節點(自動負載均衡)
  • redis cluster 的 hash slot 演算法
優點
  • 無中心架構,支持動態擴容,對業務透明
  • 具備Sentinel的監控和自動Failover(故障轉移)能力
  • 客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可
  • 高性能,客戶端直連redis服務,免去了proxy代理的損耗
缺點
  • 運維也很復雜,資料遷移需要人工干預
  • 只能使用0號資料庫
  • 不支持批量操作(pipeline管道操作)
  • 分布式邏輯和存盤模塊耦合等

三十一、集群方案- 基于客戶端分配

簡介
客戶端發送請求到一個代理組件,代理決議客戶端的資料,并將請求轉發至正確的節點,最后將結果回復給客戶端,
特征
  • 透明接入,業務程式不用關心后端Redis實體,切換成本低
  • Proxy 的邏輯和存盤的邏輯是隔離的
  • 代理層多了一次轉發,性能有所損耗
業界開源方案
  • Twtter開源的Twemproxy
  • 豌豆莢開源的Codis

三十二、Redis 主從架構

  • 單機的 redis,能夠承載的 QPS 大概就在上萬到幾萬不等,對于快取來說,一般都是用來支撐讀高并發的,因此架構做成主從(master-slave)架構,一主多從,主負責寫,并且將資料復制到其它的slave 節點,從節點負責讀,所有的讀請求全部走從節點,這樣也可以很輕松實作水平擴容,支撐讀高并發,
  • redis replication -> 主從架構 -> 讀寫分離 -> 水平擴容支撐讀高并發
redis replication 的核心機制
  • redis 采用異步方式復制資料到 slave 節點,不過 redis2.8 開始,slave node 會周期性地確認自己每次復制的資料量;
  • 一個 master node 是可以配置多個 slave node 的;
  • slave node 也可以連接其他的 slave node;
  • slave node 做復制的時候,不會 block master node 的正常作業;
  • slave node 在做復制的時候,也不會 block 對自己的查詢操作,它會用舊的資料集來提供服務;但是復制完成的時候,需要洗掉舊資料集,加載新資料集,這個時候就會暫停對外服務了;
  • slave node 主要用來進行橫向擴容,做讀寫分離,擴容的 slave node 可以提高讀的吞吐量,

注意

  • 如果采用了主從架構,那么建議必須開啟 master node 的持久化,不建議用 slave node 作為master node 的資料熱備,因為那樣的話,如果你關掉 master 的持久化,可能在 master 宕機重啟的時候資料是空的,然后可能一經過復制,slave node 的資料也丟了,
  • 另外,master 的各種備份方案,也需要做,萬一本地的所有檔案丟失了,從備份中挑選一份 rdb去恢復 master,這樣才能確保啟動的時候,是有資料的,即使采用了后續講解的高可用機制,slave node 可以自動接管 master node,但也可能 sentinel 還沒檢測到 master failure,master node 就自動重啟了,還是可能導致上面所有的 slave node 資料被清空,

redis 主從復制的核心原理

  • 當啟動一個 slave node 的時候,它會發送一個 PSYNC 命令給 master node,如果這時 slave node 初次連接到 master node,那么會觸發一次 full resynchronization 全量復制,
  • 此時 master 會啟動一個后臺執行緒,開始生成一份 RDB 快照檔案,同時還會將從客戶端 client 新收到的所有寫命令快取在記憶體中,RDB 檔案生成完畢后, master會將這個 RDB 發送給 slave,slave 會先寫入本地磁盤,然后再從本地磁盤加載到記憶體中,接著 master 會將記憶體中快取的寫命令發送到 slave,slave 也會同步這些資料,
  • slave node 如果跟 master node 有網路故障,斷開了連接,會自動重連,連接之后 master node僅會復制給 slave 部分缺少的資料,

程序原理

  • 1. 當從庫和主庫建立MS關系后,會向主資料庫發送 SYNC 命令
  • 2. 主庫接收到 SYNC 命令后會開始在后臺保存快照(RDB持久化程序),并將期間接收到的寫命令快取起來
  • 3. 當快照完成后,主Redis會將快照檔案和所有快取的寫命令發送給從Redis
  • 4. 從Redis接收到后,會載入快照檔案并且執行收到的快取的命令
  • 5. 之后,主Redis每當接收到寫命令時就會將命令發送從Redis,從而保證資料的一致

缺點
所有的slave節點資料的復制和同步都由master節點來處理,會造成 master 節點壓力太大,使用主從從結構來解決,

三十三、Redis集群的主從復制模型是怎樣的?

為了使在部分節點失敗或者大部分節點無法通信的情況下集群仍然可用,所以集群使用了主從復制模型,每個節點都會有N-1個復制品,

三十四、生產環境中的 redis 是怎么部署的?

redis cluster,10 臺機器,5 臺機器部署了 redis 主實體,另外 5 臺機器部署了 redis 的從實體,每個主實體掛了一個從實體,5 個節點對外提供讀寫服務,每個節點的讀寫高峰qps可能可以達到每秒 5 萬,5 臺機器最多是 25 萬讀寫請求/s,
機器是什么配置?
  • 32G 記憶體+ 8 核 CPU + 1T 磁盤,但是分配給 redis 行程的是10g記憶體,一般線上生產環境,redis 的記憶體盡量不要超過 10g,超過 10g 可能會有問題,
  • 5 臺機器對外提供讀寫,一共有 50g 記憶體,因為每個主實體都掛了一個從實體,所以是高可用的,任何一個主實體宕機,都會自動故障遷移,redis 從實體會自動變成主實體繼續提供讀寫服務,
你往記憶體里寫的是什么資料?每條資料的大小是多少?
商品資料,每條資料是 10kb,100 條資料是 1mb,10 萬條資料是 1g,常駐記憶體的是 200 萬條商品資料,占用記憶體是 20g,僅僅不到總記憶體的 50%,目前高峰期每秒就是 3500 左右的請求量,

三十五、說說Redis哈希槽的概念?

Redis集群沒有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽,集群的每個節點負責一部分hash槽,

三十六、Redis集群會有寫操作丟失嗎?為什么?

Redis并不能保證資料的強一致性,這意味著在實際中集群在特定的條件下可能會丟失寫操作,

三十七、Redis集群之間是如何復制的?

異步復制

三十八、Redis集群最大節點個數是多少?

16384個

三十九、Redis集群如何選擇資料庫?

Redis集群目前無法做資料庫選擇,默認在0資料庫,

四十、Redis是單執行緒的,如何提高多核CPU的利用率?

可以在同一個服務器部署多個Redis的實體,并把他們當作不同的服務器來使用,在某些時候,無論如何一個服務器是不夠的, 所以,如果你想使用多個CPU,你可以考慮一下分片(shard),

四十一、為什么要做Redis磁區?

磁區可以讓Redis管理更大的記憶體,Redis將可以使用所有機器的記憶體,如果沒有磁區,你最多只能使用一臺機器的記憶體,磁區使Redis的計算能力通過簡單地增加計算機得到成倍提升,Redis的網路帶寬也會隨著計算機和網卡的增加而成倍增長,

四十二、你知道有哪些Redis磁區實作方案?

  • 客戶端磁區就是在客戶端就已經決定資料會被存盤到哪個redis節點或者從哪個redis節點讀取,大多數客戶端已經實作了客戶端磁區,
  • 代理磁區意味著客戶端將請求發送給代理,然后代理決定去哪個節點寫資料或者讀資料,代理根據磁區規則決定請求哪些Redis實體,然后根據Redis的回應結果回傳給客戶端,
  • redis和memcached的一種代理實作就是Twemproxy查詢路由(Query routing) 的意思是客戶端隨機地請求任意一個redis實體,然后由Redis將請求轉發給正確的Redis節點,Redis Cluster實作了一種混合形式的查詢路由,但并不是直接將請求從一個redis節點轉發到另一個redis節點,而是在客戶端的幫助下直接redirected到正確的redis節點,

四十三、Redis磁區有什么缺點?

  • 涉及多個key的操作通常不會被支持,例如你不能對兩個集合求交集,因為他們可能被存盤到不同的Redis實體(實際上這種情況也有辦法,但是不能直接使用交集指令),
  • 同時操作多個key,則不能使用Redis事務
  • 磁區使用的粒度是key,不能使用一個非常長的排序key存盤一個資料集(The partitioning granularity is the key, so it is not possible to shard a dataset with a single huge key like a very big sorted set)
  • 當使用磁區的時候,資料處理會非常復雜,例如為了備份你必須從不同的Redis實體和主機同時收集RDB / AOF檔案,
  • 磁區時動態擴容或縮容可能非常復雜,Redis集群在運行時增加或者洗掉Redis節點,能做到最大程度對用戶透明地資料再平衡,但其他一些客戶端磁區或者代理磁區方法則不支持這種特性,然而,有一種預分片的技術也可以較好的解決這個問題,

四十四、Redis實作分布式鎖

  • Redis為單行程單執行緒模式,采用佇列模式將并發訪問變成串行訪問,且多客戶端對Redis的連接并不存在競爭關系,Redis中可以使用 setNx 命令實作分布式鎖,
  • 當且僅當 key 不存在,將 key 的值設為 value, 若給定的 key 已經存在,則 setNx 不做任何動作
  • SETNX 是『SET if Not eXists』(如果不存在,則 SET)的簡寫,
  • 回傳值:設定成功,回傳 1 ,設定失敗,回傳 0 ,

  • 使用setNx完成同步鎖的流程及事項如下:
  • 使用SETNX命令獲取鎖,若回傳0(key已存在,鎖已存在)則獲取失敗,反之獲取成功
  • 為了防止獲取鎖后程式出現例外,導致其他執行緒/行程呼叫setNx命令總是回傳0而進入死鎖狀態,需要為該key設定一個“合理”的過期時間釋放鎖,使用DEL命令將鎖資料洗掉,

四十五、如何解決 Redis 的并發競爭 Key 問題

  • 所謂 Redis 的并發競爭 Key 的問題也就是多個系統同時對一個 key 進行操作,但是最后執行的順序和我們期望的順序不同,這樣也就導致了結果的不同!
  • 推薦一種方案:分布式鎖(zookeeper 和 redis 都可以實作分布式鎖),(如果不存在 Redis 的并發競爭 Key 問題,不要使用分布式鎖,這樣會影響性能)
  • 基于zookeeper臨時有序節點可以實作的分布式鎖,大致思想為:每個客戶端對某個方法加鎖時,在zookeeper上的與該方法對應的指定節點的目錄下,生成一個唯一的瞬時有序節點,判斷是否獲取鎖的方式很簡單,只需要判斷有序節點中序號最小的一個, 當釋放鎖的時候,只需將這個瞬時節點洗掉即可,同時,其可以避免服務宕機導致的鎖無法釋放,而產生的死鎖問題,完成業務流程后,洗掉對應的子節點釋放鎖,
  • 在實踐中,當然是從以可靠性為主,所以首推Zookeeper,

四十六、分布式Redis是前期做還是后期規模上來了再做好?為什么?

  • 既然Redis是如此的輕量(單實體只使用1M記憶體),為防止以后的擴容,最好的辦法就是一開始就啟動較多實體,即便你只有一臺服務器,你也可以一開始就讓Redis以分布式的方式運行,使用磁區,在同一臺服務器上啟動多個實體,
  • 一開始就多設定幾個Redis實體,例如32或者64個實體,對大多數用戶來說這操作起來可能比較麻煩,但是從長久來看做這點犧牲是值得的,這樣的話,當你的資料不斷增長,需要更多的Redis服務器時,你需要做的就是僅僅將Redis實體從一臺服務遷移到另外一臺服務器而已(而不用考慮重新磁區的問題),
  • 一旦你添加了另一臺服務器,你需要將你一半的Redis實體從第一臺機器遷移到第二臺機器,

四十七、什么是 RedLock

Redis 官方站提出了一種權威的基于 Redis 實作分布式鎖的方式名叫 Redlock,此種方式比原先的單節點的方法更安全,它可以保證以下特性:
  • 1. 安全特性:互斥訪問,即永遠只有一個 client 能拿到鎖
  • 2. 避免死鎖:最終 client 都可能拿到鎖,不會出現死鎖的情況,即使原本鎖住某資源的 client crash 了或者出現了網路磁區
  • 3. 容錯性:只要大部分 Redis 節點存活就可以正常提供服務

四十八、什么是redis穿透?

就是用戶請求透過redis去請求mysql服務器,導致mysql壓力過載,但一個web服務里,極容易出現瓶頸的就是mysql,所以才讓redis去分擔mysql 的壓力,所以這種問題是萬萬要避免的,
解決方法:
  • 1. 從快取取不到的資料,在資料庫中也沒有取到,這時也可以將key-value對寫為key-null,快取有效時間可以設定短點,如30秒(設定太長會導致正常情況也沒法使用),這樣可以防止攻擊用戶反復用同一個id暴力攻擊,
  • 2. 介面層增加校驗,如用戶鑒權校驗,id做基礎校驗,id<=0的直接攔截,
  • 3. 采用布隆過濾器,將所有可能存在的資料哈希到一個足夠大的 bitmap 中,一個一定不存在的資料會被這個 bitmap 攔截掉,從而避免了對底層存盤系統的查詢壓力,

四十九、什么是redis雪崩?

就是redis服務由于負載過大而宕機,導致mysql的負載過大也宕機,最終整個系統癱瘓,
解決方法:
  • 1. redis集群,將原來一個人干的作業,分發給多個人干
  • 2. 快取預熱(關閉外網訪問,先開啟mysql,通過預熱腳本將熱點資料寫入快取中,啟動快取,開啟外網服務)
  • 3. 資料不要設定相同的生存時間,不然過期時,redis壓力會大

五十、什么是redis擊穿?

高并發下,由于一個key失效,而導致多個執行緒去mysql查同一業務資料并存到redis(并發下,存了多份資料),而一段時間后,多份資料同時失效,導致壓力驟增
解決方法:
  • 1. 分級快取(快取兩份資料,第二份資料生存時間長一點作為備份,第一份資料用于被請求命中,如果第二份資料被命中說明第一份資料已經過期,要去mysql請求資料重新快取兩份資料)
  • 2. 計劃任務(假如資料生存時間為30分鐘,計劃任務就20分鐘執行一次更新快取資料)

五十一、快取預熱

快取預熱就是系統上線后,將相關的快取資料直接加載到快取系統,這樣就可以避免在用戶請求的時候,先查詢資料庫,然后再將資料快取的問題!用戶直接查詢事先被預熱的快取資料!
解決方案
  • 1. 直接寫個快取重繪頁面,上線時手工操作一下;
  • 2. 資料量不大,可以在專案啟動的時候自動進行加載;
  • 3. 定時重繪快取;

五十二、快取降級

當訪問量劇增、服務出現問題(如回應時間慢或不回應)或非核心服務影響到核心流程的性能時,仍然需要保證服務還是可用的,即使是有損服務,系統可以根據一些關鍵資料進行自動降級,也可以配置開關實作人工降級,快取降級的最終目的是保證核心服務可用,即使是有損的,而且有些服務是無法降級的(如加入購物車、結算),在進行降級之前要對系統進行梳理,看看系統是不是可以丟卒保帥;從而梳理出哪些必須誓死保護,哪些可降級;比如可以參考日志級別設定預案:
  • 1. 一般:比如有些服務偶爾因為網路抖動或者服務正在上線而超時,可以自動降級;
  • 2. 警告:有些服務在一段時間內成功率有波動(如在95~100%之間),可以自動降級或人工降級,并發送告警;
  • 3. 錯誤:比如可用率低于90%,或者資料庫連接池被打爆了,或者訪問量突然猛增到系統能承受的最大閥值,此時可以根據情況自動降級或者人工降級;
  • 4. 嚴重錯誤:比如因為特殊原因資料錯誤了,此時需要緊急人工降級,
服務降級的目的,是為了防止Redis服務故障,導致資料庫跟著一起發生雪崩問題,因此,對于不重要的快取資料,可以采取服務降級策略,例如一個比較常見的做法就是,Redis出現問題,不去資料庫查詢,而是直接回傳默認值給用戶,

五十三、熱點資料和冷資料

  • 熱點資料,快取才有價值,
  • 對于冷資料而言,大部分資料可能還沒有再次訪問到就已經被擠出記憶體,不僅占用記憶體,而且價值不大,頻繁修改的資料,看情況考慮使用快取,
  • 對于熱點資料,比如我們的某IM產品,生日祝福模塊,當天的壽星串列,快取以后可能讀取數十萬次,再舉個例子,某導航產品,我們將導航資訊,快取以后可能讀取數百萬次,
  • 資料更新前至少讀取兩次,快取才有意義,這個是最基本的策略,如果快取還沒有起作用就失效了,那就沒有太大價值了,
  • 那存不存在,修改頻率很高,但是又不得不考慮快取的場景呢?有!比如,這個讀取介面對資料庫的壓力很大,但是又是熱點資料,這個時候就需要考慮通過快取手段,減少資料庫的壓力,比如我們的某助手產品的,點贊數,收藏數,分享數等是非常典型的熱點資料,但是又不斷變化,此時就需要將資料同步保存到Redis快取,減少資料庫壓力,

五十四、快取熱點key

快取中的一個Key(比如一個促銷商品),在某個時間點過期的時候,恰好在這個時間點對這個Key有大量的并發請求過來,這些請求發現快取過期一般都會從后端DB加載資料并回設到快取,這個時候大并發的請求可能會瞬間把后端DB壓垮,
解決方案
對快取查詢加鎖,如果KEY不存在,就加鎖,然后查DB入快取,然后解鎖;其他行程如果發現有鎖就等待,然后等解鎖后回傳資料或者進入DB查詢,

五十五、Redis支持的Java客戶端都有哪些?官方推薦用哪個?

Redisson、Jedis、lettuce等等,官方推薦使用Redisson,

五十六、Redis和Redisson有什么關系?

Redisson是一個高級的分布式協調Redis客服端,能幫助用戶在分布式環境中輕松實作一些Java的物件 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map,ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog),

五十七、Jedis與Redisson對比有什么優缺點?

  • Jedis是Redis的Java實作的客戶端,其API提供了比較全面的Redis命令的支持;
  • Redisson實作了分布式和可擴展的Java資料結構,和Jedis相比,功能較為簡單,不支持字串操作,不支持排序、事務、管道、磁區等Redis特性,
  • Redisson的宗旨是促進使用者對Redis的關注分離,從而讓使用者能夠將精力更集中地放在處理業務邏輯上,

五十八、Redis與Memcached的區別

兩者都是非關系型記憶體鍵值資料庫,現在公司一般都是用 Redis 來實作快取,而且 Redis 自身也越來越強大了!Redis 與 Memcached 主要有以下不同:
  • 1. memcached所有的值均是簡單的字串,redis作為其替代者,支持更為豐富的資料型別
  • 2. redis的速度比memcached快很多
  • 3. redis可以持久化其資料

五十九、如何保證快取與資料庫雙寫時的資料一致性?

  • 你只要用快取,就可能會涉及到快取與資料庫雙存盤雙寫,你只要是雙寫,就一定會有資料一致性的問題,那么你如何解決一致性問題?
  • 一般來說,就是如果你的系統不是嚴格要求 快取+資料庫 必須一致性的話,快取可以稍微的跟資料庫偶爾有不一致的情況,最好不要做這個方案,
  • 讀請求和寫請求串行化,串到一個記憶體佇列里去,這樣就可以保證一定不會出現不一致的情況,串行化之后,就會導致系統的吞吐量會大幅度的降低,用比正常情況下多幾倍的機器去支撐線上的一個請求,
  • 還有一種方式就是可能會暫時產生不一致的情況,但是發生的幾率特別小,就是先更新資料庫,然后再洗掉快取,
問題場景1:
先寫快取,再寫資料庫,快取寫成功,資料庫寫失敗
描述:
快取寫成功,但寫資料庫失敗或者回應延遲,則下次讀取(并發讀)快取時,就出現臟讀
解決:
這個寫快取的方式,本身就是錯誤的,需要改為先寫資料庫,把舊快取置為失效;讀取資料的時候,如果快取不存在,則讀取資料庫再寫快取
問題場景2:
先寫資料庫,再寫快取,資料庫寫成功,快取寫失敗
描述:
寫資料庫成功,但寫快取失敗,則下次讀取(并發讀)快取時,則讀不到資料
解決:
快取使用時,假如讀快取失敗,先讀資料庫,再回寫快取的方式實作
問題場景3:
需要快取異步重繪
描述:
指資料庫操作和寫快取不在一個操作步驟中,比如在分布式場景下,無法做到同時寫快取或需要異步重繪(補救措施)時候
解決:
確定哪些資料適合此類場景,根據經驗值確定合理的資料不一致時間,用戶資料重繪的時間間隔

六十、Redis常見性能問題和解決方案?

  • 1. Master最好不要做任何持久化作業,包括記憶體快照和AOF日志檔案,特別是不要啟用記憶體快照做持久化,
  • 2. 如果資料比較關鍵,某個Slave開啟AOF備份資料,策略為每秒同步一次,
  • 3. 為了主從復制的速度和連接的穩定性,Slave和Master最好在同一個局域網內,
  • 4. 盡量避免在壓力較大的主庫上增加從庫
  • 5. Master呼叫BGRE WRITE AOF重寫AOF檔案,AOF在重寫的時候會占大量的CPU和記憶體資源,導致服務load過高,出現短暫服務暫停現象,
  • 6. 為了Master的穩定性,主從復制不要用圖狀結構,用單向鏈表結構更穩定,即主從關系為:
  • Master<–Slave1<–Slave2<–Slave3…,這樣的結構也方便解決單點故障問題,實作Slave對Master的替換,也即,如果Master掛了,可以立馬啟用Slave1做Master,其他不變,

六十一、Redis官方為什么不提供Windows版本?

因為目前Linux版本已經相當穩定,而且用戶量很大,無需開發windows版本,反而會帶來兼容性等問題,

六十二、一個字串型別的值能存盤最大容量是多少?

512M

六十三、Redis如何做大量資料插入?

Redis2.6開始redis-cli支持一種新的被稱之為pipe mode的新模式用于執行大量資料插入作業,

六十四、假如Redis里面有1億個key,其中有10w個key是以某個固定的已知的前綴開頭的,如果將它們全部找出來?

  • 使用keys指令可以掃出指定模式的key串列,
  • 對方接著追問:如果這個redis正在給線上的業務提供服務,那使用keys指令會有什么問題?
  • 這個時候你要回答redis關鍵的一個特性:redis的單執行緒的,keys指令會導致執行緒阻塞一段時間,線上服務會停頓,直到指令執行完畢,服務才能恢復,這個時候可以使用scan指令,scan指令可以無阻塞的提取出指定模式的key串列,但是會有一定的重復概率,在客戶端做一次去重就可以了,但是整體所花費的時間會比直接用keys指令長,

六十五、Redis如何實作延時佇列

使用sorted set,使用時間戳做score, 訊息內容作為key,呼叫zadd來生產訊息,消費者使用zrang by score獲取n秒之前的資料做輪詢處理,

六十六、Redis回收行程如何作業的?

  • 1. 一個客戶端運行了新的命令,添加了新的資料,
  • 2. Redis檢查記憶體使用情況,如果大于maxmemory的限制,則根據設定好的策略進行回收,
  • 3. 一個新的命令被執行,等等,
  • 4. 所以我們不斷地穿越記憶體限制的邊界,通過不斷達到邊界然后不斷地回識訓到邊界以下,如果一個命令的結果導致大量記憶體被使用(例如很大的集合的交集保存到一個新的鍵),不用多久記憶體限制就會被這個記憶體使用量超越,

六十七、Redis回收使用的是什么演算法?

LRU演算法

 

 

 

 

落葉他鄉樹 寒燈獨夜人

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/536196.html

標籤:其他

上一篇:OpenGL ES Windows 搭建環境(MFC版本)

下一篇:計算機等級考試二級C語言程式設計專項訓練題——程式設計題(六)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more