<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Redis面試突擊專用

          共 7798字,需瀏覽 16分鐘

           ·

          2021-01-12 20:39


          作者 |?_睶_

          來源 |?https://blog.csdn.net/Butterfly_resting/article/details/89668661

          本文的面試題如下:Redis 持久化機制 緩存雪崩、緩存穿透、緩存預熱、緩存更新、緩存降級等問題 熱點數(shù)據(jù)和冷數(shù)據(jù)是什么 Memcache與Redis的區(qū)別都有哪些?單線程的redis為什么這么快 redis的數(shù)據(jù)類型,以及每種數(shù)據(jù)類型的使用場景,Redis 內(nèi)部結(jié)構(gòu) redis的過期策略以及內(nèi)存淘汰機制【~】 Redis 為什么是單線程的,優(yōu)點 如何解決redis的并發(fā)競爭key問題 Redis 集群方案應該怎么做?都有哪些方案?有沒有嘗試進行多機redis 的部署?如何保證數(shù)據(jù)一致的?對于大量的請求怎么樣處理 Redis 常見性能問題和解決方案?講解下Redis線程模型 為什么Redis的操作是原子性的,怎么保證原子性的?Redis事務 Redis實現(xiàn)分布式鎖


          Redis 持久化機制

          Redis是一個支持持久化的內(nèi)存數(shù)據(jù)庫,通過持久化機制把內(nèi)存中的數(shù)據(jù)同步到硬盤文件來保證數(shù)據(jù)持久化。當Redis重啟后通過把硬盤文件重新加載到內(nèi)存,就能達到恢復數(shù)據(jù)的目的。實現(xiàn):單獨創(chuàng)建fork()一個子進程,將當前父進程的數(shù)據(jù)庫數(shù)據(jù)復制到子進程的內(nèi)存中,然后由子進程寫入到臨時文件中,持久化的過程結(jié)束了,再用這個臨時文件替換上次的快照文件,然后子進程退出,內(nèi)存釋放。

          RDB是Redis默認的持久化方式。按照一定的時間周期策略把內(nèi)存的數(shù)據(jù)以快照的形式保存到硬盤的二進制文件。即Snapshot快照存儲,對應產(chǎn)生的數(shù)據(jù)文件為dump.rdb,通過配置文件中的save參數(shù)來定義快照的周期。( 快照可以是其所表示的數(shù)據(jù)的一個副本,也可以是數(shù)據(jù)的一個復制品。)?AOF:Redis會將每一個收到的寫命令都通過Write函數(shù)追加到文件最后,類似于MySQL的binlog。當Redis重啟是會通過重新執(zhí)行文件中保存的寫命令來在內(nèi)存中重建整個數(shù)據(jù)庫的內(nèi)容。當兩種方式同時開啟時,數(shù)據(jù)恢復Redis會優(yōu)先選擇AOF恢復。

          緩存雪崩、緩存穿透、緩存預熱、緩存更新、緩存降級等問題

          緩存雪崩我們可以簡單的理解為:由于原有緩存失效,新緩存未到期間 (例如:我們設置緩存時采用了相同的過期時間,在同一時刻出現(xiàn)大面積的緩存過期),所有原本應該訪問緩存的請求都去查詢數(shù)據(jù)庫了,而對數(shù)據(jù)庫CPU和內(nèi)存造成巨大壓力,嚴重的會造成數(shù)據(jù)庫宕機。從而形成一系列連鎖反應,造成整個系統(tǒng)崩潰。?解決辦法:大多數(shù)系統(tǒng)設計者考慮用加鎖( 最多的解決方案)或者隊列的方式保證來保證不會有大量的線程對數(shù)據(jù)庫一次性進行讀寫,從而避免失效時大量的并發(fā)請求落到底層存儲系統(tǒng)上。還有一個簡單方案就時講緩存失效時間分散開。

          二、緩存穿透?緩存穿透是指用戶查詢數(shù)據(jù),在數(shù)據(jù)庫沒有,自然在緩存中也不會有。這樣就導致用戶查詢的時候,在緩存中找不到,每次都要去數(shù)據(jù)庫再查詢一遍,然后返回空(相當于進行了兩次無用的查詢)。這樣請求就繞過緩存直接查數(shù)據(jù)庫,這也是經(jīng)常提的緩存命中率問題。?解決辦法;?最常見的則是采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中,一個一定不存在的數(shù)據(jù)會被這個bitmap攔截掉,從而避免了對底層存儲系統(tǒng)的查詢壓力。另外也有一個更為簡單粗暴的方法,如果一個查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在,還是系統(tǒng)故障),我們?nèi)匀话堰@個空結(jié)果進行緩存,但它的過期時間會很短,最長不超過五分鐘。通過這個直接設置的默認值存放到緩存,這樣第二次到緩沖中獲取就有值了,而不會繼續(xù)訪問數(shù)據(jù)庫,這種辦法最簡單粗暴。5TB的硬盤上放滿了數(shù)據(jù),請寫一個算法將這些數(shù)據(jù)進行排重。如果這些數(shù)據(jù)是一些32bit大小的數(shù)據(jù)該如何解決?如果是64bit的呢?

          對于空間的利用到達了一種極致,那就是Bitmap和布隆過濾器(Bloom Filter)。Bitmap:典型的就是哈希表 缺點是,Bitmap對于每個元素只能記錄1bit信息,如果還想完成額外的功能,恐怕只能靠犧牲更多的空間、時間來完成了。

          布隆過濾器(推薦)?就是引入了k(k>1)k(k>1)個相互獨立的哈希函數(shù),保證在給定的空間、誤判率下,完成元素判重的過程。它的優(yōu)點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識別率和刪除困難。Bloom-Filter算法的核心思想就是利用多個不同的Hash函數(shù)來解決“沖突”。Hash存在一個沖突(碰撞)的問題,用同一個Hash得到的兩個URL的值有可能相同。為了減少沖突,我們可以多引入幾個Hash,如果通過其中的一個Hash值我們得出某元素不在集合中,那么該元素肯定不在集合中。只有在所有的Hash函數(shù)告訴我們該元素在集合中時,才能確定該元素存在于集合中。這便是Bloom-Filter的基本思想。Bloom-Filter一般用于在大數(shù)據(jù)量的集合中判定某元素是否存在。?受提醒補充:緩存穿透與緩存擊穿的區(qū)別?緩存擊穿:是指一個key非常熱點,在不停的扛著大并發(fā),大并發(fā)集中對這一個點進行訪問,當這個key在失效的瞬間,持續(xù)的大并發(fā)就穿破緩存,直接請求數(shù)據(jù)。解決方案;在訪問key之前,采用SETNX(set if not exists)來設置另一個短期key來鎖住當前key的訪問,訪問結(jié)束再刪除該短期key。增:給一個我公司處理的案例:背景雙機拿token,token在存一份到redis,保證系統(tǒng)在token過期時都只有一個線程去獲取token;線上環(huán)境有兩臺機器,故使用分布式鎖實現(xiàn)。

          三、緩存預熱?緩存預熱這個應該是一個比較常見的概念,相信很多小伙伴都應該可以很容易的理解,緩存預熱就是系統(tǒng)上線后,將相關的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。這樣就可以避免在用戶請求的時候,先查詢數(shù)據(jù)庫,然后再將數(shù)據(jù)緩存的問題!用戶直接查詢事先被預熱的緩存數(shù)據(jù)!解決思路:1、直接寫個緩存刷新頁面,上線時手工操作下;2、數(shù)據(jù)量不大,可以在項目啟動的時候自動進行加載;3、定時刷新緩存;

          四、緩存更新?除了緩存服務器自帶的緩存失效策略之外(Redis默認的有6中策略可供選擇),我們還可以根據(jù)具體的業(yè)務需求進行自定義的緩存淘汰,常見的策略有兩種:(1)定時去清理過期的緩存;(2)當有用戶請求過來時,再判斷這個請求所用到的緩存是否過期,過期的話就去底層系統(tǒng)得到新數(shù)據(jù)并更新緩存。兩者各有優(yōu)劣,第一種的缺點是維護大量緩存的key是比較麻煩的,第二種的缺點就是每次用戶請求過來都要判斷緩存失效,邏輯相對比較復雜!具體用哪種方案,大家可以根據(jù)自己的應用場景來權衡。五、緩存降級?當訪問量劇增、服務出現(xiàn)問題(如響應時間慢或不響應)或非核心服務影響到核心流程的性能時,仍然需要保證服務還是可用的,即使是有損服務。系統(tǒng)可以根據(jù)一些關鍵數(shù)據(jù)進行自動降級,也可以配置開關實現(xiàn)人工降級。降級的最終目的是保證核心服務可用,即使是有損的。而且有些服務是無法降級的(如加入購物車、結(jié)算)。以參考日志級別設置預案:(1)一般:比如有些服務偶爾因為網(wǎng)絡抖動或者服務正在上線而超時,可以自動降級;(2)警告:有些服務在一段時間內(nèi)成功率有波動(如在95~100%之間),可以自動降級或人工降級,并發(fā)送告警;(3)錯誤:比如可用率低于90%,或者數(shù)據(jù)庫連接池被打爆了,或者訪問量突然猛增到系統(tǒng)能承受的最大閥值,此時可以根據(jù)情況自動降級或者人工降級;(4)嚴重錯誤:比如因為特殊原因數(shù)據(jù)錯誤了,此時需要緊急人工降級。

          服務降級的目的,是為了防止Redis服務故障,導致數(shù)據(jù)庫跟著一起發(fā)生雪崩問題。因此,對于不重要的緩存數(shù)據(jù),可以采取服務降級策略,例如一個比較常見的做法就是,Redis出現(xiàn)問題,不去數(shù)據(jù)庫查詢,而是直接返回默認值給用戶。

          熱點數(shù)據(jù)和冷數(shù)據(jù)是什么

          熱點數(shù)據(jù),緩存才有價值 對于冷數(shù)據(jù)而言,大部分數(shù)據(jù)可能還沒有再次訪問到就已經(jīng)被擠出內(nèi)存,不僅占用內(nèi)存,而且價值不大。頻繁修改的數(shù)據(jù),看情況考慮使用緩存 對于上面兩個例子,壽星列表、導航信息都存在一個特點,就是信息修改頻率不高,讀取通常非常高的場景。對于熱點數(shù)據(jù),比如我們的某IM產(chǎn)品,生日祝福模塊,當天的壽星列表,緩存以后可能讀取數(shù)十萬次。再舉個例子,某導航產(chǎn)品,我們將導航信息,緩存以后可能讀取數(shù)百萬次。**數(shù)據(jù)更新前至少讀取兩次,**緩存才有意義。這個是最基本的策略,如果緩存還沒有起作用就失效了,那就沒有太大價值了。那存不存在,修改頻率很高,但是又不得不考慮緩存的場景呢?有!比如,這個讀取接口對數(shù)據(jù)庫的壓力很大,但是又是熱點數(shù)據(jù),這個時候就需要考慮通過緩存手段,減少數(shù)據(jù)庫的壓力,比如我們的某助手產(chǎn)品的,點贊數(shù),收藏數(shù),分享數(shù)等是非常典型的熱點數(shù)據(jù),但是又不斷變化,此時就需要將數(shù)據(jù)同步保存到Redis緩存,減少數(shù)據(jù)庫壓力。

          Memcache與Redis的區(qū)別都有哪些?

          1)、存儲方式 Memecache把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會掛掉,數(shù)據(jù)不能超過內(nèi)存大小。Redis有部份存在硬盤上,redis可以持久化其數(shù)據(jù) 2)、數(shù)據(jù)支持類型 memcached所有的值均是簡單的字符串,redis作為其替代者,支持更為豐富的數(shù)據(jù)類型 ,提供list,set,zset,hash等數(shù)據(jù)結(jié)構(gòu)的存儲 3)、使用底層模型不同 它們之間底層實現(xiàn)方式 以及與客戶端之間通信的應用協(xié)議不一樣。Redis直接自己構(gòu)建了VM 機制 ,因為一般的系統(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會浪費一定的時間去移動和請求。4). value 值大小不同:Redis 最大可以達到 512M;memcache 只有 1mb。5)redis的速度比memcached快很多 6)Redis支持數(shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份。

          單線程的redis為什么這么快

          (一)純內(nèi)存操作 (二)單線程操作,避免了頻繁的上下文切換 (三)采用了非阻塞I/O多路復用機制

          redis的數(shù)據(jù)類型,以及每種數(shù)據(jù)類型的使用場景

          回答:一共五種 (一)String 這個其實沒啥好說的,最常規(guī)的set/get操作,value可以是String也可以是數(shù)字。一般做一些復雜的計數(shù)功能的緩存。(二)hash 這里value存放的是結(jié)構(gòu)化的對象,比較方便的就是操作其中的某個字段。博主在做單點登錄的時候,就是用這種數(shù)據(jù)結(jié)構(gòu)存儲用戶信息,以cookieId作為key,設置30分鐘為緩存過期時間,能很好的模擬出類似session的效果。(三)list 使用List的數(shù)據(jù)結(jié)構(gòu),可以做簡單的消息隊列的功能。另外還有一個就是,可以利用lrange命令,做基于redis的分頁功能,性能極佳,用戶體驗好。本人還用一個場景,很合適—取行情信息。就也是個生產(chǎn)者和消費者的場景。LIST可以很好的完成排隊,先進先出的原則。(四)set 因為set堆放的是一堆不重復值的集合。所以可以做全局去重的功能。為什么不用JVM自帶的Set進行去重?因為我們的系統(tǒng)一般都是集群部署,使用JVM自帶的Set,比較麻煩,難道為了一個做一個全局去重,再起一個公共服務,太麻煩了。另外,就是利用交集、并集、差集等操作,可以計算共同喜好,全部的喜好,自己獨有的喜好等功能。(五)sorted set sorted set多了一個權重參數(shù)score,集合中的元素能夠按score進行排列??梢宰雠判邪駪?,取TOP N操作。

          Redis 內(nèi)部結(jié)構(gòu)

          • dict 本質(zhì)上是為了解決算法中的查找問題(Searching)是一個用于維護key和value映射關系的數(shù)據(jù)結(jié)構(gòu),與很多語言中的Map或dictionary類似。本質(zhì)上是為了解決算法中的查找問題(Searching)
          • sds sds就等同于char * 它可以存儲任意二進制數(shù)據(jù),不能像C語言字符串那樣以字符’\0’來標識字符串的結(jié) 束,因此它必然有個長度字段。
          • skiplist (跳躍表) 跳表是一種實現(xiàn)起來很簡單,單層多指針的鏈表,它查找效率很高,堪比優(yōu)化過的二叉平衡樹,且比平衡樹的實現(xiàn),
          • quicklist
          • ziplist 壓縮表 ziplist是一個編碼后的列表,是由一系列特殊編碼的連續(xù)內(nèi)存塊組成的順序型數(shù)據(jù)結(jié)構(gòu),

          redis的過期策略以及內(nèi)存淘汰機制

          redis采用的是定期刪除+惰性刪除策略。為什么不用定時刪除策略? 定時刪除,用一個定時器來負責監(jiān)視key,過期則自動刪除。雖然內(nèi)存及時釋放,但是十分消耗CPU資源。在大并發(fā)請求下,CPU要將時間應用在處理請求,而不是刪除key,因此沒有采用這一策略. 定期刪除+惰性刪除是如何工作的呢??定期刪除,redis默認每個100ms檢查,是否有過期的key,有過期key則刪除。需要說明的是,redis不是每個100ms將所有的key檢查一次,而是隨機抽取進行檢查(如果每隔100ms,全部key進行檢查,redis豈不是卡死)。因此,如果只采用定期刪除策略,會導致很多key到時間沒有刪除。于是,惰性刪除派上用場。也就是說在你獲取某個key的時候,redis會檢查一下,這個key如果設置了過期時間那么是否過期了?如果過期了此時就會刪除。采用定期刪除+惰性刪除就沒其他問題了么? 不是的,如果定期刪除沒刪除key。然后你也沒即時去請求key,也就是說惰性刪除也沒生效。這樣,redis的內(nèi)存會越來越高。那么就應該采用內(nèi)存淘汰機制。在redis.conf中有一行配置

          maxmemory-policy?volatile-lru

          該配置就是配內(nèi)存淘汰策略的(什么,你沒配過?好好反省一下自己)?volatile-lru:從已設置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰?volatile-ttl:從已設置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過期的數(shù)據(jù)淘汰?volatile-random:從已設置過期時間的數(shù)據(jù)集(server.db[i].expires)中任意選擇數(shù)據(jù)淘汰?allkeys-lru:從數(shù)據(jù)集(server.db[i].dict)中挑選最近最少使用的數(shù)據(jù)淘汰?allkeys-random:從數(shù)據(jù)集(server.db[i].dict)中任意選擇數(shù)據(jù)淘汰?no-enviction(驅(qū)逐):禁止驅(qū)逐數(shù)據(jù),新寫入操作會報錯 ps:如果沒有設置 expire 的key, 不滿足先決條件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行為, 和 noeviction(不刪除) 基本上一致。

          Redis 為什么是單線程的

          官方FAQ表示,因為Redis是基于內(nèi)存的操作,CPU不是Redis的瓶頸,Redis的瓶頸最有可能是機器內(nèi)存的大小或者網(wǎng)絡帶寬。既然單線程容易實現(xiàn),而且CPU不會成為瓶頸,那就順理成章地采用單線程的方案了(畢竟采用多線程會有很多麻煩?。㏑edis利用隊列技術將并發(fā)訪問變?yōu)榇性L問 1)絕大部分請求是純粹的內(nèi)存操作(非常快速)2)采用單線程,避免了不必要的上下文切換和競爭條件 3)非阻塞IO優(yōu)點:1.速度快,因為數(shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap的優(yōu)勢就是查找和操作的時間復雜度都是O(1) \2. 支持豐富數(shù)據(jù)類型,支持string,list,set,sorted set,hash 3.支持事務,操作都是原子性,所謂的原子性就是對數(shù)據(jù)的更改要么全部執(zhí)行,要么全部不執(zhí)行 \4. 豐富的特性:可用于緩存,消息,按key設置過期時間,過期后將會自動刪除如何解決redis的并發(fā)競爭key問題

          同時有多個子系統(tǒng)去set一個key。這個時候要注意什么呢?不推薦使用redis的事務機制。因為我們的生產(chǎn)環(huán)境,基本都是redis集群環(huán)境,做了數(shù)據(jù)分片操作。你一個事務中有涉及到多個key操作的時候,這多個key不一定都存儲在同一個redis-server上。因此,redis的事務機制,十分雞肋。(1)如果對這個key操作,不要求順序:準備一個分布式鎖,大家去搶鎖,搶到鎖就做set操作即可 (2)如果對這個key操作,要求順序:分布式鎖+時間戳。假設這會系統(tǒng)B先搶到鎖,將key1設置為{valueB 3:05}。接下來系統(tǒng)A搶到鎖,發(fā)現(xiàn)自己的valueA的時間戳早于緩存中的時間戳,那就不做set操作了。以此類推。(3) 利用隊列,將set方法變成串行訪問也可以redis遇到高并發(fā),如果保證讀寫key的一致性 對redis的操作都是具有原子性的,是線程安全的操作,你不用考慮并發(fā)問題,redis內(nèi)部已經(jīng)幫你處理好并發(fā)的問題了。

          Redis 集群方案應該怎么做?都有哪些方案?

          1.twemproxy,大概概念是,它類似于一個代理方式, 使用時在本需要連接 redis 的地方改為連接 twemproxy, 它會以一個代理的身份接收請求并使用一致性 hash 算法,將請求轉(zhuǎn)接到具體 redis,將結(jié)果再返回 twemproxy。缺點:twemproxy 自身單端口實例的壓力,使用一致性 hash 后,對 redis 節(jié)點數(shù)量改變時候的計算值的改變,數(shù)據(jù)無法自動移動到新的節(jié)點。

          2.codis,目前用的最多的集群方案,基本和 twemproxy 一致的效果,但它支持在 節(jié)點數(shù)量改變情況下,舊節(jié)點數(shù)據(jù)可恢復到新 hash 節(jié)點

          3.redis cluster3.0 自帶的集群,特點在于他的分布式算法不是一致性 hash,而是 hash 槽的概念,以及自身支持節(jié)點設置從節(jié)點。具體看官方文檔介紹。

          有沒有嘗試進行多機redis 的部署?如何保證數(shù)據(jù)一致的?

          主從復制,讀寫分離 一類是主數(shù)據(jù)庫(master)一類是從數(shù)據(jù)庫(slave),主數(shù)據(jù)庫可以進行讀寫操作,當發(fā)生寫操作的時候自動將數(shù)據(jù)同步到從數(shù)據(jù)庫,而從數(shù)據(jù)庫一般是只讀的,并接收主數(shù)據(jù)庫同步過來的數(shù)據(jù),一個主數(shù)據(jù)庫可以有多個從數(shù)據(jù)庫,而一個從數(shù)據(jù)庫只能有一個主數(shù)據(jù)庫。

          對于大量的請求怎么樣處理

          redis是一個單線程程序,也就說同一時刻它只能處理一個客戶端請求;redis是通過IO多路復用(select,epoll, kqueue,依據(jù)不同的平臺,采取不同的實現(xiàn))來處理多個客戶端請求的

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

          (1) Master 最好不要做任何持久化工作,如 RDB 內(nèi)存快照和 AOF 日志文件 (2) 如果數(shù)據(jù)比較重要,某個 Slave 開啟 AOF 備份數(shù)據(jù),策略設置為每秒同步一次 (3) 為了主從復制的速度和連接的穩(wěn)定性, Master 和 Slave 最好在同一個局域網(wǎng)內(nèi) (4) 盡量避免在壓力很大的主庫上增加從庫 (5) 主從復制不要用圖狀結(jié)構(gòu),用單向鏈表結(jié)構(gòu)更為穩(wěn)定,即:Master <- Slave1 <- Slave2 <- Slave3…

          講解下Redis線程模型

          文件事件處理器包括分別是套接字、 I/O 多路復用程序、 文件事件分派器(dispatcher)、 以及事件處理器。使用 I/O 多路復用程序來同時監(jiān)聽多個套接字, 并根據(jù)套接字目前執(zhí)行的任務來為套接字關聯(lián)不同的事件處理器。當被監(jiān)聽的套接字準備好執(zhí)行連接應答(accept)、讀?。╮ead)、寫入(write)、關閉(close)等操作時, 與操作相對應的文件事件就會產(chǎn)生, 這時文件事件處理器就會調(diào)用套接字之前關聯(lián)好的事件處理器來處理這些事件。I/O 多路復用程序負責監(jiān)聽多個套接字, 并向文件事件分派器傳送那些產(chǎn)生了事件的套接字。?工作原理:?1)I/O 多路復用程序負責監(jiān)聽多個套接字, 并向文件事件分派器傳送那些產(chǎn)生了事件的套接字。盡管多個文件事件可能會并發(fā)地出現(xiàn), 但 I/O 多路復用程序總是會將所有產(chǎn)生事件的套接字都入隊到一個隊列里面, 然后通過這個隊列, 以有序(sequentially)、同步(synchronously)、每次一個套接字的方式向文件事件分派器傳送套接字:當上一個套接字產(chǎn)生的事件被處理完畢之后(該套接字為事件所關聯(lián)的事件處理器執(zhí)行完畢), I/O 多路復用程序才會繼續(xù)向文件事件分派器傳送下一個套接字。如果一個套接字又可讀又可寫的話, 那么服務器將先讀套接字, 后寫套接字.

          為什么Redis的操作是原子性的,怎么保證原子性的?

          對于Redis而言,命令的原子性指的是:一個操作的不可以再分,操作要么執(zhí)行,要么不執(zhí)行。Redis的操作之所以是原子性的,是因為Redis是單線程的。Redis本身提供的所有API都是原子操作,Redis中的事務其實是要保證批量操作的原子性。多個命令在并發(fā)中也是原子性的嗎?不一定, 將get和set改成單命令操作,incr 。使用Redis的事務,或者使用Redis+Lua==的方式實現(xiàn).

          Redis事務

          Redis事務功能是通過MULTI、EXEC、DISCARD和WATCH 四個原語實現(xiàn)的 Redis會將一個事務中的所有命令序列化,然后按順序執(zhí)行。1.redis 不支持回滾“Redis 在事務失敗時不進行回滾,而是繼續(xù)執(zhí)行余下的命令”, 所以 Redis 的內(nèi)部可以保持簡單且快速。2.如果在一個事務中的命令出現(xiàn)錯誤,那么所有的命令都不會執(zhí)行;3.如果在一個事務中出現(xiàn)運行錯誤,那么正確的命令會被執(zhí)行。注:redis的discard只是結(jié)束本次事務,正確命令造成的影響仍然存在.

          1)MULTI命令用于開啟一個事務,它總是返回OK。MULTI執(zhí)行之后,客戶端可以繼續(xù)向服務器發(fā)送任意多條命令,這些命令不會立即被執(zhí)行,而是被放到一個隊列中,當EXEC命令被調(diào)用時,所有隊列中的命令才會被執(zhí)行。2)EXEC:執(zhí)行所有事務塊內(nèi)的命令。返回事務塊內(nèi)所有命令的返回值,按命令執(zhí)行的先后順序排列。當操作被打斷時,返回空值 nil 。3)通過調(diào)用DISCARD,客戶端可以清空事務隊列,并放棄執(zhí)行事務, 并且客戶端會從事務狀態(tài)中退出。4)WATCH 命令可以為 Redis 事務提供 check-and-set (CAS)行為??梢员O(jiān)控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之后的事務就不會執(zhí)行,監(jiān)控一直持續(xù)到EXEC命令。

          Redis實現(xiàn)分布式鎖

          Redis為單進程單線程模式,采用隊列模式將并發(fā)訪問變成串行訪問,且多客戶端對Redis的連接并不存在競爭關系Redis中可以使用SETNX命令實現(xiàn)分布式鎖。將 key 的值設為 value ,當且僅當 key 不存在。若給定的 key 已經(jīng)存在,則 SETNX 不做任何動作解鎖:使用 del key 命令就能釋放鎖 解決死鎖:1)通過Redis中expire()給鎖設定最大持有時間,如果超過,則Redis來幫我們釋放鎖。2) 使用 setnx key “當前系統(tǒng)時間+鎖持有的時間”和getset key “當前系統(tǒng)時間+鎖持有的時間”組合的命令就可以實現(xiàn)。

          更多好文章

          1. Java高并發(fā)系列(共34篇)
          2. MySql高手系列(共27篇)
          3. Maven高手系列(共10篇)
          4. Mybatis系列(共12篇)
          5. 聊聊db和緩存一致性常見的實現(xiàn)方式
          6. 接口冪等性這么重要,它是什么?怎么實現(xiàn)?
          7. 泛型,有點難度,會讓很多人懵逼,那是因為你沒有看這篇文章!

          瀏覽 61
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷国产成人精品一区二区 | 操骚逼自拍| 91干干干| 五月天福利视频 | 久久伊人AV |