github:
實際使用根據自己專案情況,比如常見的快取配置資料,首頁資料,排行榜資料等等。
為什麼要用快取,用哪種快取中介軟體,這個應該也是我們在使用前要思考的,而不是追風。
使用快取一般解決兩個問題,高效能和高併發。
高效能
實在是太慢了。這個時候,可以根據業務情況,這些資料加到快取,2ms 就查詢出來,效能提高了 250 倍。
高併發
mysql 關係型資料庫單機 qps 到 2000 就很難承受,系統在趕上高峰期的時候,如果瞬間過來一萬流量,哪你的資料庫可能就
各種超時,各種連線獲取失敗,因為連線被佔滿了,可能導致系統崩潰。對於這些流量,可以先放到快取,從快取逐步處理,
快取是走記憶體的,記憶體天然就支撐高併發。也可以使用 mq 做流量削峰處理。
快取與資料庫不一致問題:
用快取一般都會出現資料不一致問題,如何處理?
1)採用延時雙刪策略。先刪除快取,在寫資料庫,休眠 n 毫秒之後,再次刪除快取。
2)非同步更新快取(基於 binlog 同步機制)。canal 模擬 mysql 從庫協議,監聽 binlog 的寫操作,
傳送 mq,消費 mq 非同步更新快取。
無論使用上面拿兩種方式,都應該根據自己業務快取特性加上對應的快取過期時間,即時出現意外,
也只是短期的快取與資料庫不一致,快取過期後會重新從資料庫載入資料,達到最終一致性。
快取雪崩,快取穿透,快取擊穿問題:
快取雪崩,比如 a 系統高峰期的時候 qps 達到 5000,如果快取掛掉了,所有請求訪問都打到了 mysql,
mysql 扛不住就掛掉了。如果用的 redis,有以下預防方案:
事前:保證 redis 的高可用,主從+哨兵,redis cluster,避免全盤崩潰。
事中:本地 ehcache 快取 + hystrix(sentinel) 限流&降級,避免 mysql ***。
事後:redis 持久化,一旦重啟,自動從磁碟上載入資料,快速恢復快取資料。
快取穿透,如果被黑客攻擊,大量請求呼叫系統,都是快取沒有的 key,請求都會打到資料庫,
可以在沒有從資料庫查到的情況下,給 key 設定乙個預設值以及適當的超時時間,避免用同樣的 key 一直訪問,
一直訪問資料庫,這樣做只是增加了攻擊的難度,還需要對 key 結合業務做一些正確性校驗,比如 key 是使用者 id 自增整數,
查詢前如果 id 是負數或者非數字等則降級返回,不實際處理請求。
快取擊穿,快取擊穿一般是系統存放了乙個非常熱點的資料,集中高併發對 key 進行訪問,一單 key 過期了,
大量的請求擊穿了快取,湧向了資料庫,就向螢幕被人打了一槍,戳了個洞。一般預防方案需要根據業務情況而定:
1)如果資料幾乎不變動,可以設定為永久資料;
2)如果資料變動不是很頻繁,比如用 redis 做分布式鎖,拿不到鎖的等著,拿到的執行,完事後釋放鎖,讓其他執行緒獲取鎖;
3)如果變動比較頻繁,以適當的定時任務或定時指令碼重新整理快取,避免過期後快取擊穿情況;
redis 採用 key-value 鍵值對方式進行儲存。
string 可以是字串、整數或浮點數。
redis 的 hash(雜湊)是乙個可以儲存多個鍵值對之間的對映。與 string 型別一樣,
雜湊儲存的值既可以是字串又可以是數字值,並且使用者也可以對雜湊的數字值進行
自增或自減操作。hash 最適合做的就是儲存物件,占用更少的記憶體空間,並且更方便
整個物件的訪問。
set 是 string 型別的無序集合。set 是通過 hash table 實現的。
sorted set 是 set 的乙個公升級版本,主要是在 set 的基礎上增加了順序屬性。
list 是乙個鍊錶結構,主要功能有 push,pop 等,push,pop可以操作鍊錶,
可以在鍊錶的頭部,尾部新增刪除元素,可以實現 list 作為棧或佇列的操作。
快取資料都是存在記憶體中,如果沒有持久化,服務重啟或掛掉,資料將丟失。
rdb:rdb 是 redis 記憶體資料的乙個二進位制快照檔案,定期備份資料到 dump.rdb 檔案,可以設定頻率。
這種方式的優點就是通過乙個執行緒定期刷資料,保證 redis 的高效能,重啟恢復也比較快,缺點就是如果設定 5s 備份一次,
如果還沒到下乙個 5s redis 崩盤了,還沒備份的這幾秒資料將會丟失。
aof:aof 是一種通過備份 redis 寫操作命令實現的備份,優點就是資料一般不會丟,缺點就是重啟恢復太慢了,
備份檔案的所有寫命令。
redis 4.x 混合持久化:rdb 和 aof 各有千秋,混合持久化是備份資料將兩種結合在一起,舊資料以二進位制儲存,
最新資料以寫命令儲存,這樣在恢復的時候 dump 恢復很快,只需要執行少量的寫命令即可,恢復快而幾乎不丟資料。
說實話,memcached 業務裡面現在很少有人用,但是問快取的問題,又喜歡問下區別,主要是看你用快取之前有沒有去調研過
redis 好些。
redis 支援豐富的資料結構,string、hash(雜湊)、set(無序集合)、sorted set(有序集合)、list(列表)。
memcached 只能支援類似 string 結構,就是乙個簡單 key-value。
redis 在3.x之前只有哨兵模式(sentinel),哨兵模式效能太低,之後出現集群模式(cluster),效能很高,
每個集群擁有不同的槽,按鍵值雜湊到不同 redis 服務進行處理,橫向擴充套件十分方便,高可用也***。
memcached 依賴客戶端集中進行分片,沒有集群模式,只能做主從高可用。
redis 只能使用單核,memcached 可以使用多核,redis 處理小資料效能比 memcached 更高,但是處理儲存的資料比較大,
效能比不上 memcached。
redis 是單執行緒模型的,因為內部的檔案事件處理器是單執行緒的。單執行緒如何保證效能?
主要採用的是 io 多路復用機制同時監聽多個 socket,將請求事件壓入到記憶體佇列中,再由事件分派器根據
socket 上的事件型別選擇對應的處理器進行處理。如果了解過 nio,很容易理解這段話的意思。
多個 socket 可能會併發產生不同的操作,每個操作對應不同的檔案事件,但是 io 多路復用程式會監聽多個 socket,
會將產生事件的 socket 放入佇列中排隊,事件分派器每次從佇列中取出乙個 socket,根據 socket 的事件型別交給對應的
事件處理器進行處理。
1、純記憶體操作;
2、核心基於非阻塞的 io 多路復用機制;
3、底層是用 c 語言寫的,更接近與作業系統打交道的語言;
4、單執行緒能避免多執行緒存在的上下文切換,以及鎖競爭等影響效能的問題;
redis 為什麼要有過期策略,主要是因為 redis 資料都存在記憶體裡面,而記憶體空間是有限的,放滿了豈不是用不了,
得根據一定的策略騰出空間來使用。
定期刪除+惰性刪除。
定期刪除
redis 每隔 100ms,隨機抽取 key,判斷是否過期,過期後自動刪除,但是這麼做如果有些 key 一直沒有隨機到,
哪就一直清除不調,通過惰性刪除來處理隨機不到的過期 key。
惰性刪除
惰性就是在根據這個 key 操作的時候,再判斷是否過期,過期了刪除,但是即便這樣做了,還是有問題,
如果乙個 key 過期了,沒有被隨機到,也沒有操作到,哪也會一直存在記憶體裡面,占用空間。
所以 redis 採取了下乙個方案,快取淘汰機制。
noeviction: 當記憶體不足以容納新寫入資料時,返回錯誤,一般不用,不能讓新的資料寫不進來。
allkeys-lru:當記憶體不足以容納新寫入資料時,在鍵空間中,移除最近最少使用的key,一般用這個,
因為很久以前的 key 還用,業務設計得可能就有問題。
allkeys-random:當記憶體不足以容納新寫入資料時,在鍵空間中,隨機移除某個 key,這個太狠了,一般不用,業務就亂套了。
volatile-lru:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,移除最近最少使用的 key,一般不用這個,
這個只限於過期的鍵值,不能有漏網之魚。
volatile-random:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,隨機移除某個 key,記憶體淘汰不全。
volatile-ttl:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,有更早過期時間的 key 優先移除,記憶體淘汰不全。
根據 key 的維度不同,分為三類:
noeviction 直接報錯;
allkeys-xx 所有鍵空間找最近最少使用或隨機方式清除 key;
volatile-xx 過期時間鍵空間找最近最少使用或隨機方式或過期時間最早清除 key;
持續更新完善中......
django rest framework快取應用
在我們web製作過程中進場使用到快取技術,那麼今天python中的一種簡單便捷的快取技術與大家分享 以下是在省 市 區 聯動的位址查詢做的快取處理 使用快取 省市區的資料是經常被使用者查詢使用的,而且資料基本不變化,所以我們可以將省市區資料進行快取處理,減少資料庫的查詢次數。在django rest...
WPF與緩動 四 弧形緩動
wpf與緩動 四 弧形緩動 周銀輝 弧形緩動就是其緩動曲線為一段圓弧,如何我們假設圓弧上的點的斜率為速度的話,那麼可以想像其速度的變化多麼具有戲劇性,其加速或減速來得很突然,與5次緩動差不多.參考以下 圓形緩動 protected override double getcurrentvaluecor...
深度緩紋理
create a texture object storing color glgentextures 1,m udepthtexid glbindtexture gl texture 2d,m udepthtexid gltexparameterf gl texture 2d,gl texture...