<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Not Only SQL的簡稱。NoSQL是解決傳統的RDBMS在應對某些問題時比較乏力而提出的。
即非關係型資料庫,它們不保證關係資料的ACID特性,資料之間一般沒有關聯,在擴充套件上就非常容易實現,並且擁有較高的效能。
redis是nosql的典型代表,也是目前網際網路公司的必用技術。
redis是鍵值(Key-Value)儲存資料庫,主要會使用到雜湊表。大多數時候是直接以快取的形式被使用,使得請求不直接存取到磁碟,所以效率方面是很不錯的,完全能滿足中小型企業的使用需求。
常用資料型別
使用頻率上string和hash會高一些,各個型別有各自的操作命令,無非增刪改查,具體的命令後面我會整理一份。
web應用在眾多請求同時發生時,可能會導致資料讀取、儲存上出現錯誤,即發生髒讀、髒資料生成。
在分散式專案下,會出現更多的問題。
並行時,本質其實就是多個請求同時進來了,沒辦法正確的去進行處理。
可以將所有的請求放在 一個佇列,讓請求們按照一個順序,挨個進來執行業務邏輯。目前成熟的解決方案就是使用訊息佇列,下次我會整理一篇訊息佇列處理高並行的;
還有一個方法是直接將並行轉為序列,Java提供了synchronized,即同步,不過這個在效率要求比較苛刻的地方 或者 分散式專案下還是不太合適的方案,這裡就引出了使用redis來實現分散式鎖,從而解決並行問題。
在分散式專案中,使用一個唯一、通用、效率高的標識,來表示上鎖和解鎖。
redis實現起來很簡單,即對一個key是否存在來表示是否上鎖、是否解鎖。
以string型別舉例:
Integer stock = goodsMapper.getStock(); if (stock > 0) { stock =- 1; goodsMapper.updateStock(stock); }
以上是最簡單的秒殺虛擬碼,我們嘗試用redis實現分散式鎖。
// 這裡是錯誤程式碼,只是一個思考過程,請耐心看完哦 String key = "REDIS_DISTRIBUTION_LOCKER"; // 分散式鎖名稱 String value = jedisUtils.get(key); if (value != null) { // 未上鎖 // wingzingliu jedisUtils.set(key, 1); // 上鎖 Integer stock = goodsMapper.getStock(); if (stock > 0) { stock =- 1; goodsMapper.updateStock(stock); jedisUtils.del(key); // 釋放鎖 } }
以上程式碼可能會出現一個問題,就是當同時多個請求進來,某次多個請求都拿到value為空,執行緒A進入if 走到// wingzingliu這裡的時候,還未上鎖,其他請求也進來了,這樣就會出現髒資料了。
這裡的程式碼問題就是出在沒有考慮原子性問題。
所以我們要使用到redis的一個setNx命令,本質也是設定值,但是這是一個原子操作,執行之後會返回是否設定成功。
redis> SETNX job "programmer" # job 設定成功 (integer) 1 redis> SETNX job "code-farmer" # 嘗試覆蓋 job ,失敗 (integer) 0 redis> GET job # 沒有被覆蓋 "programmer"
重點關注 當有值時,會失敗,返回0。所以我們的程式碼會改造成以下這個樣子。
// 這裡是錯誤程式碼,只是一個思考過程,請耐心看完哦 String key = "REDIS_DISTRIBUTION_LOCKER"; // 分散式鎖名稱 Long result = jedisUtils.setNx(key, 1); if (result > 0) { // 上鎖成功,進入邏輯 // wingzingliu1 Integer stock = goodsMapper.getStock(); if (stock > 0) { stock =- 1; goodsMapper.updateStock(stock); System.out.println("購買成功!"); } else { System.out.println("沒有庫存了!"); } // wingzingliu2 jedisUtils.del(key); // 釋放鎖 }
以上我們就可以保證原子性,能正確的按照順序去處理。
可是還有一個隱藏的問題,就是當某個執行緒執行上鎖成功後,在wingzingliu1到wingzingliu2之間時,程式拋異常了,那麼程式終止了,就無法釋放鎖,其他執行緒也都進不來了。
解決方案是加上try catch finally塊,在finally裡面去釋放鎖。
可是那如果是宕機呢?上鎖之後宕機了,finally裡面的依然不會執行,鎖沒有得到釋放,不手動處理的情況下,以後所有執行緒也無法進入。
所以引入了redis的過期時間,到了某個時間自動解鎖。
// 這裡是不夠完善的程式碼,請耐心看完哦 try { String key = "REDIS_DISTRIBUTION_LOCKER"; // 分散式鎖名稱 Long result = jedisUtils.setNx(key, 1, 30); // 假設處理邏輯需要20s左右,設定了30秒自動過期 if (result > 0) { // 上鎖成功,進入邏輯 Integer stock = goodsMapper.getStock(); if (stock > 0) { stock =- 1; goodsMapper.updateStock(stock); System.out.println("購買成功!"); } else { System.out.println("沒有庫存了!"); } } } catch (Exception e) { } finally { jedisUtils.del(key); // 釋放鎖 }
以上是比較完善的分散式鎖了,但是還有一個小瑕疵,就是假設某一次請求A處理的很慢,預計20s但是跑了35s,到了30s的時候鎖過期了,其他請求就自然進來了。
這不僅僅會導致一次並行,當請求A處理完時,依然會執行釋放鎖,這實際上是下一個執行緒上的鎖。以此類推,整個並行控制就亂了。
理論上可以設定一個更大的key過期時間,但是並不是最好的解決方案。這裡就引出一個概念:鎖續命。
如其名,給鎖續命。實現就是 當鎖快過期的時候,去延長鎖的時間。假設一個30s的鎖,每個10s去檢測一下,鎖是否還在 如果在就重新延長至30s。這樣就避免掉了上面的這個可能出現的問題。
這裡使用一個定時任務,週期性的呼叫即可。
剛剛對key設定的value是1,其實能使用請求ID來進行儲存,這樣就能知道鎖是由哪個請求上的,在解鎖的時候 也可以避免解鎖了其他執行緒上的鎖。具體由前端傳遞,或者由伺服器端以某種規則生成都可以。
至此我們就使用redis,一步一步的解決了在分散式專案下的並行問題。redis不是唯一的解決方案,但是對於大部分網際網路公司來說,是一個很成熟、效能不錯、便捷的方案。
還可以使用synchronized(非分散式專案)、mq 、zookeeper等方案去實現分散式鎖 以 解決高並行問題。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45