欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用redis的increment()方法實(shí)現(xiàn)計(jì)數(shù)器功能案例

 更新時(shí)間:2020年11月24日 10:14:00   作者:無關(guān)痛癢qaq  
這篇文章主要介紹了使用redis的increment()方法實(shí)現(xiàn)計(jì)數(shù)器功能案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧

一直知道redis可以用來實(shí)現(xiàn)計(jì)數(shù)器功能,但是之前沒有實(shí)際使用過,昨天碰到一個(gè)需求:用戶掃碼當(dāng)天達(dá)到20次即提示:當(dāng)日掃碼次數(shù)達(dá)到上限!

當(dāng)時(shí)就想到使用redis的遞增方法increment()來實(shí)現(xiàn)計(jì)數(shù)器功能,一定要注意redisTemplate和stringRedisTemplate的使用

首先設(shè)置key:

該key我使用了用戶id和當(dāng)天日期作為key的一部分,date:xxxx-xx-xx格式,這樣一來該用戶在第二天掃碼的時(shí)候又是一個(gè)新key,因?yàn)槿掌诓煌?/p>

設(shè)置key的過期時(shí)間:

實(shí)現(xiàn)計(jì)數(shù)器功能:

通過使用上面的方法,redis的計(jì)數(shù)器功能就可以實(shí)現(xiàn)了。

在使用過程過遇到的問題:

在使用的過程中,老是會(huì)拋錯(cuò):ERR value is not an integer or out of range

后來發(fā)現(xiàn)當(dāng)時(shí)我使用的方法底層用的redisTemplate和stringRedisTemplate串了,當(dāng)時(shí)setKey的時(shí)候用的方法底層是

stringRedisTemplate,后面我想get(key)的時(shí)候方法底層的模板使用的是redisTemplate,后面統(tǒng)一了一下模板的使用,然后計(jì)數(shù)

器功能正常運(yùn)行不再拋錯(cuò)。

看過很多文章說是序列化器的鍋,increment方法必須是stringRedisTemplate模板才能使用,但是我在實(shí)際使用的時(shí)候也確實(shí)是

用了redisTemplate,這個(gè)具體原因我還在看,此次使用中最主要的問題是setKey的時(shí)候使用的模板和取key的時(shí)候使用的模板不

一致導(dǎo)致的。寫個(gè)筆記記錄一下,一個(gè)坑不踩第二遍。大家如果遇到一樣的問題可以一起討論學(xué)習(xí)一下。

補(bǔ)充知識:認(rèn)識redis:redis計(jì)數(shù)器與數(shù)量控制

這篇文章是我個(gè)人對redis的一些理解,可以幫助大家系統(tǒng)的認(rèn)識redis。本文的目標(biāo)讀者是使用過redis,但對redis了解不深的朋友。文章內(nèi)容以redis為主,也會(huì)少量提到memcached。文章從redis的設(shè)計(jì)目的、工作模式、應(yīng)用場景等方面闡述,最后會(huì)講解一些具體的應(yīng)用場景,還會(huì)夾帶一些代碼作為“干貨”。

鑒于本人水平有限,文中如有不準(zhǔn)確的內(nèi)容,敬請斧正。

redis是什么

redis是一種內(nèi)存型的數(shù)據(jù)存儲器,使用場景

數(shù)據(jù)庫

緩存

消息代理(message broker)

同memcached對比

memcached是分布式的內(nèi)存對象緩存系統(tǒng),設(shè)計(jì)意圖為通過緩解數(shù)據(jù)庫壓力來加快web應(yīng)用的響應(yīng)速度。

上面的描述分別被放在了redis和memcached的官網(wǎng)首頁最顯眼的位置,這也回答了redis和memcached的本質(zhì)區(qū)別。

redis的工作模式

redis的工作模式為單進(jìn)程,這意味著redis只能利用到一個(gè)cpu內(nèi)核。 redis對請求的處理是串行的,對于同時(shí)涌進(jìn)來的多個(gè)請求,redis首先把請求存入隊(duì)列,按請求到達(dá)的先后順序串行處理。

了解單進(jìn)程和串行這兩個(gè)特點(diǎn),有助于我們使用redis時(shí)“揚(yáng)長避短”。

之前有同事提到過,為何redis不適合存儲大塊的數(shù)據(jù)?從redis的工作模式我們可以窺知一二:大塊的數(shù)據(jù)意味著需要較長的io時(shí)間,包括內(nèi)存io和網(wǎng)絡(luò)的io,cpu資源在io過程中是一直被占用的,這會(huì)阻塞其它請求,從而影響redis的整體性能。

數(shù)據(jù)類型

大家對redis的數(shù)據(jù)類型已經(jīng)比較熟悉了,主要有以下5種。

string

list

hash

set

sorted set

各種數(shù)據(jù)類型的常用操作

string

set,get,setnx,setex,psetex

拼接

增加、減少(整數(shù)型字符串)

位操作

list

入列,出列(這兩個(gè)命令都有阻塞模式)

按排位獲取部分元素

hash

設(shè)置某個(gè)索引

獲取某個(gè)索引

增加/減少某個(gè)索引的值(整數(shù)型字符串)

獲取所有索引的值

set

集合是一個(gè)數(shù)學(xué)概念,啰嗦提一下:集合中的元素都是唯一的

加入元素

刪除元素

檢查元素是否在集合

獲取集合中的元素?cái)?shù)量

取差集/并集/交集

元素轉(zhuǎn)移(從集合a移至集合b)

zset

有序集合,每個(gè)元素都有一個(gè)分值,用于對元素進(jìn)行排序

取交集/并集

獲取一個(gè)元素的rank

獲取分值在某個(gè)范圍內(nèi)的元素?cái)?shù)量

獲取分值在某個(gè)范圍內(nèi)的元素

按rank范圍獲取元素

redis事務(wù)

redis事務(wù)和我們熟悉的mysql事務(wù)有所區(qū)別,它們的相同在于都是對一個(gè)或一組命令的打包執(zhí)行,不同的地方在于redis事務(wù)不可回滾。

redis的事務(wù)具有原子性,一個(gè)事務(wù)的執(zhí)行有兩種結(jié)果

完全執(zhí)行

完全不執(zhí)行

一些不可抗力因素除外,如服務(wù)掛掉,服務(wù)器斷電。redis事務(wù)是一個(gè)獨(dú)立的請求,執(zhí)行過程中會(huì)阻塞其它請求。

實(shí)現(xiàn)redis事務(wù)有以下兩種方式

multi-exec

lua腳本

multi-exec

127.0.0.1:6380[1]> set counter1 1
OK
127.0.0.1:6380[1]> set counter2 2
OK
127.0.0.1:6380[1]> set counter3 3
OK
127.0.0.1:6380[1]>
127.0.0.1:6380[1]>
127.0.0.1:6380[1]> multi
OK
127.0.0.1:6380[1]> incr counter1
QUEUED
127.0.0.1:6380[1]> sadd counter2 1
QUEUED
127.0.0.1:6380[1]> incr counter3
QUEUED
127.0.0.1:6380[1]> exec
1) (integer) 2
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) (integer) 4

從上面的事務(wù)執(zhí)行輸出可以看到,我們的sadd執(zhí)行出錯(cuò)了,原因是操作的數(shù)據(jù)類型不正確,但redis沒有中止整個(gè)事務(wù),而是繼續(xù)往下執(zhí)行。redis這么做是有道理的,見參考文獻(xiàn)1。

multi-exec和watch的組合可以實(shí)現(xiàn)類似于mysql事務(wù)的功能,如果被watch的key在事務(wù)執(zhí)行前被修改了,redis會(huì)放棄執(zhí)行事務(wù)。

lua腳本

和multi-exec相比,lua腳本的優(yōu)勢在于靈活性,也可以減少一定的網(wǎng)絡(luò)時(shí)間消耗(為什么?)。

鑒于redis的工作模式,不建議用lua腳本實(shí)現(xiàn)耗時(shí)較長的事務(wù)。

下面模擬了lua腳本的執(zhí)行阻塞其它請求的場景,大家可以親自試一下。

client 1

eval "local i=0; while(i<1000000) do redis.call('keys', '*'); i=i+1; end" 0

client 2

incr counter

redis的實(shí)際應(yīng)用

類型:string

命令:setnx name alice |set name alice NX

返回true則鎖定成功,否則鎖定失敗

了解了redis的工作模式,就知道為什么用redis實(shí)現(xiàn)鎖是如此容易了。用memcache也可以實(shí)現(xiàn)鎖,但代碼層面要復(fù)雜一些,參見memcached.cas。

事件隊(duì)列

類型:zset

命令:zadd,zrangebyscore,zrem

適合存儲一些需要順序處理的事件,將事件的score值設(shè)為時(shí)間戳或自增id即可。為什么用list不可以?

計(jì)數(shù)器

類型:string

命令:incr

抽獎(jiǎng)限額

類型:string

命令:incrby

某活動(dòng)的現(xiàn)金紅包每天最多只能發(fā)送10000元。下面是這段邏輯的偽代碼,如果能夠舉一反三,這段代碼將大有用武之地。大家可以用并發(fā)測試工具測試這段代碼,如果發(fā)現(xiàn)了bug,或者能有更好的實(shí)現(xiàn)方式,請不要告訴我 -_-

$key = 'max_amount';
$amountLimit = 10000;

if (!$currAmount = Redis::get($key)) {
  $currAmount = 9990;     // 從持久化數(shù)據(jù)庫獲取當(dāng)前已發(fā)放金額
  // 初始化
  Redis::setnx($key, $currAmount);
}

if ($currAmount >= $amountLimit) {
  // 超出限額退出
}

// 抽獎(jiǎng)金額
$rewardAmount = 10;
if ($rewardAmount > $amountLimit - $currAmount) {
  $rewardAmount = $amountLimit - $currAmount;
}
if (Redis::incrby($key, $rewardAmount) > $amountLimit) {
  // 超出限額退出
} else {
  // 成功抽獎(jiǎng)
}

初始化為何用setnx,用set可以嗎?

最后為何使用incrby,不用可以嗎?

總結(jié)

文章內(nèi)容不多,所謂的干貨更少,這和作者的水平有關(guān),也和文章的定位有關(guān)。細(xì)心的朋友可能發(fā)現(xiàn)了,文中有一些內(nèi)容是帶有問號的,有興趣的朋友可以加以思考。希望能給大家一個(gè)參考,也希望大家多多支持腳本之家

相關(guān)文章

最新評論