国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

詳解 mini-redis 復(fù)刻 Redis 的 I NCR 指令

數(shù)據(jù)庫(kù) Redis
本文將針對(duì)字符串操作中介紹筆者近期所復(fù)刻的鍵值自增指令的落地思路,以幫助讀者更好的理解和學(xué)習(xí)mini-redis。

因?yàn)榻诒容^忙碌,所以對(duì)于mini-redis的復(fù)刻基本處于一些指令向的完善,而本文將針對(duì)字符串操作中介紹筆者近期所復(fù)刻的鍵值自增指令的落地思路,以幫助讀者更好的理解和學(xué)習(xí)mini-redis。

對(duì)象類型前置校驗(yàn)

因?yàn)橹噶钍腔谧址僮鞯模栽趫?zhí)行INCR或者DECR之前我們都必須針對(duì)入?yún)⒌逆I值對(duì)進(jìn)行校驗(yàn),所以對(duì)于以下情況,我們都必須采用fail-fast的方式提前將失敗暴露,將鍵值對(duì)已存在,對(duì)應(yīng)的值非字符串類型(例如:字典類型),直接響應(yīng)錯(cuò)誤:

基于上述的基本概念,我們給出落地的代碼,即位于command.go的incrDecrCommand方法,可以看到我們會(huì)優(yōu)先到redis內(nèi)存中查看是否存在對(duì)應(yīng)的key,如果存在則進(jìn)行必要的類型判斷,如果非字符串類型即REDIS_STRING則直接響應(yīng)錯(cuò)誤出去,并直接返回:

func incrDecrCommand(c *redisClient, incr int64) {
 var value int64
 var oldValue int64
 var newObj *robj
 //查看鍵值對(duì)是否存在
 o := lookupKeyWrite(c.db, c.argv[1])
 //如果鍵值對(duì)存在且類型非字符串類型,直接響應(yīng)錯(cuò)誤并返回
 if o != nil && checkType(c, o, REDIS_STRING) {
  return
 }
 
 
 //......

}

對(duì)此我們也給出checkType的內(nèi)部邏輯,可以看到當(dāng)比對(duì)類型不一致時(shí)會(huì)直接輸出錯(cuò)誤并返回true,讀者可以參考注釋了解:

func checkType(c *redisClient, o *robj, rType int) bool {
 //如果類型不一致,則輸出-WRONGTYPE Operation against a key holding the wrong kind of value
 if o.robjType != rType {
  addReply(c, shared.wrongtypeerr)
  return true
 }
 return false
}

其實(shí)筆者這里也想吐槽一句redis對(duì)于函數(shù)設(shè)計(jì)的語(yǔ)義的不恰當(dāng)性,理論性合理的函數(shù)進(jìn)行校驗(yàn)時(shí)正確的做法應(yīng)該是:

  • 邏輯校驗(yàn)失敗,輸出錯(cuò)誤返回false。
  • 邏輯校驗(yàn)正確,返回true。

也只能說(shuō)因?yàn)槟承v史原因,或者設(shè)計(jì)者有著自己的主觀編碼習(xí)慣吧,本著一比一的復(fù)刻理念,筆者也沿襲了這樣的編碼思路。

基于數(shù)值池高效完成字符串轉(zhuǎn)換

針對(duì)字符串類型(可以轉(zhuǎn)數(shù)值的情況下,它也會(huì)轉(zhuǎn)數(shù)值類型),我們都是通過(guò)robj類型創(chuàng)建和維護(hù),因?yàn)槲覀儽敬嗡鶑?fù)刻的incr和decr所操作的類型是字符串中可轉(zhuǎn)為數(shù)值的對(duì)象,所以本著數(shù)值類型有跡可循的規(guī)律以及空間換時(shí)間的思想,我們提出池化思想,即將0-9999數(shù)值緩存一份數(shù)值池,后續(xù)的增減操作后處于該范圍的數(shù)值都可以直接使用數(shù)值池里對(duì)應(yīng)的robj對(duì)象,以節(jié)約robj對(duì)象創(chuàng)建的開(kāi)銷和非必要的內(nèi)存資源占用:

所以筆者在main.go中聲明sharedObjectsStruct 這個(gè)結(jié)構(gòu)體中聲明了一個(gè)integers維護(hù)常量池的robj對(duì)象:

type sharedObjectsStruct struct {
 //......
 integers       [REDIS_SHARED_INTEGERS]*robj //通用0~9999常量數(shù)值池
 //......
}

然后在createSharedObjects方法中完成初始化,后續(xù)就可以直接使用了:

func createSharedObjects() {
 //......

 var i int64
 //初始化常量池對(duì)象
 for i = 0; i < REDIS_SHARED_INTEGERS; i++ {
  //基于接口封裝數(shù)值
  num := interface{}(i)
  //生成string對(duì)象
  shared.integers[i] = createObject(REDIS_STRING, &num)
  //聲明編碼類型為int
  shared.integers[i].encoding = REDIS_ENCODING_INT
 }

 //......
}

于是我們就得出了后續(xù)的編碼邏輯:

  • 將value強(qiáng)轉(zhuǎn)為數(shù)值判斷是否超出范圍,如果超了則拋出異常。反之進(jìn)入步驟2。
  • 查看取值范圍是否大于10000,如果是則自己生成robj對(duì)象,反之采用池化數(shù)值池的robj。
  • 基于1、2生成的數(shù)值對(duì)象將鍵值對(duì)更新或者覆蓋到內(nèi)存數(shù)據(jù)庫(kù)中。
/**
 針對(duì)字符串類型的值進(jìn)行如下判斷的和轉(zhuǎn)換:
 1. 如果為空,說(shuō)明本次的key不存在,直接初始化一個(gè)空字符串,后續(xù)會(huì)直接初始化一個(gè)0值使用
 2. 如果是字符串類型,則轉(zhuǎn)為字符串類型
 3. 如果是數(shù)值類型,則先轉(zhuǎn)為字符串類型進(jìn)行后續(xù)的通用數(shù)值轉(zhuǎn)換操作保證一致性
 */
 var s string
 if o == nil {
  s = ""
 } else if isString(*o.ptr) {
  s = (*o.ptr).(string)
 } else {
  s = strconv.FormatInt((*o.ptr).(int64), 10)
 }
 //進(jìn)行類型強(qiáng)轉(zhuǎn)為數(shù)值,如果失敗,直接輸出錯(cuò)誤并返回
 if getLongLongFromObjectOrReply(c, s, &value, nil) != REDIS_OK {
  return
 }

 oldValue = value
 //如果累加超范圍則報(bào)錯(cuò)
 if (incr < 0 && oldValue < 0 && incr < (math.MinInt64-oldValue)) ||
  (incr > 0 && oldValue > 0 && incr > (math.MaxInt64-oldValue)) {
  errReply := "increment or decrement would overflow"
  addReplyError(c, &errReply)
  return
 }
 //基于incr累加的值生成value
 value += incr
 //如果超常量池范圍則封裝一個(gè)對(duì)象使用 
 if o != nil &&
  (value < 0 || value >= REDIS_SHARED_INTEGERS) &&
  (value > math.MinInt64 || value < math.MaxInt64) {
  newObj = o

  i := interface{}(value)
  o.ptr = &i
 } else if o != nil {//如果對(duì)象存在,且累加結(jié)果沒(méi)超范圍則調(diào)用createStringObjectFromLongLong獲取常量對(duì)象
  newObj = createStringObjectFromLongLong(value)
  //將寫(xiě)入結(jié)果覆蓋
  dbOverwrite(c.db, c.argv[1], newObj)
 } else {//從常量池獲取數(shù)值,然后添加鍵值對(duì)到數(shù)據(jù)庫(kù)中
  newObj = createStringObjectFromLongLong(value)
  dbAdd(c.db, c.argv[1], newObj)
 }

通用結(jié)果響應(yīng)

完成上述操作后就是將結(jié)果按照RESP協(xié)議規(guī)范將結(jié)果響應(yīng)給客戶端,按照協(xié)議要求數(shù)值類型必須用:號(hào)開(kāi)頭,所以假設(shè)我們累加結(jié)果為10,那么響應(yīng)給客戶端的結(jié)果就是10\r\n。

對(duì)應(yīng)我們的給出最后的代碼段:

//將累加后的結(jié)果返回給客戶端,按照RESP格式即 :數(shù)值\r\n,例如返回10 那么格式就是:10\r\n
 reply := *shared.colon + strconv.FormatInt(value, 10) + *shared.crlf
 addReply(c, &reply)

完整的代碼實(shí)現(xiàn)

我們來(lái)小結(jié)一下上述的實(shí)現(xiàn)思路:

  • 鍵值對(duì)查詢與校驗(yàn)。
  • 數(shù)值類型轉(zhuǎn)換與越界判斷。
  • 字符串類型強(qiáng)轉(zhuǎn)并基于取值范圍查看是否通過(guò)數(shù)值池獲取。
  • 更新或覆蓋鍵值對(duì)。
  • 將操作結(jié)果返回客戶端。

完整代碼如下:

func incrDecrCommand(c *redisClient, incr int64) {
 var value int64
 var oldValue int64
 var newObj *robj
 //查看鍵值對(duì)是否存在
 o := lookupKeyWrite(c.db, c.argv[1])
 //如果鍵值對(duì)存在且類型非字符串類型,直接響應(yīng)錯(cuò)誤并返回
 if o != nil && checkType(c, o, REDIS_STRING) {
  return
 }
 /**
 針對(duì)字符串類型的值進(jìn)行如下判斷的和轉(zhuǎn)換:
 1. 如果為空,說(shuō)明本次的key不存在,直接初始化一個(gè)空字符串,后續(xù)會(huì)直接初始化一個(gè)0值使用
 2. 如果是字符串類型,則轉(zhuǎn)為字符串類型
 3. 如果是數(shù)值類型,則先轉(zhuǎn)為字符串類型進(jìn)行后續(xù)的通用數(shù)值轉(zhuǎn)換操作保證一致性
 */
 var s string
 if o == nil {
  s = ""
 } else if isString(*o.ptr) {
  s = (*o.ptr).(string)
 } else {
  s = strconv.FormatInt((*o.ptr).(int64), 10)
 }
 //進(jìn)行類型強(qiáng)轉(zhuǎn)為數(shù)值,如果失敗,直接輸出錯(cuò)誤并返回
 if getLongLongFromObjectOrReply(c, s, &value, nil) != REDIS_OK {
  return
 }

 oldValue = value

 if (incr < 0 && oldValue < 0 && incr < (math.MinInt64-oldValue)) ||
  (incr > 0 && oldValue > 0 && incr > (math.MaxInt64-oldValue)) {
  errReply := "increment or decrement would overflow"
  addReplyError(c, &errReply)
  return
 }
 //基于incr累加的值生成value
 value += incr
 //如果超常量池范圍則封裝一個(gè)對(duì)象使用
 if o != nil &&
  (value < 0 || value >= REDIS_SHARED_INTEGERS) &&
  (value > math.MinInt64 || value < math.MaxInt64) {
  newObj = o

  i := interface{}(value)
  o.ptr = &i
 } else if o != nil { //如果對(duì)象存在,且累加結(jié)果沒(méi)超范圍則調(diào)用createStringObjectFromLongLong獲取常量對(duì)象
  newObj = createStringObjectFromLongLong(value)
  //將寫(xiě)入結(jié)果覆蓋
  dbOverwrite(c.db, c.argv[1], newObj)
 } else { //從常量池獲取數(shù)值,然后添加鍵值對(duì)到數(shù)據(jù)庫(kù)中
  newObj = createStringObjectFromLongLong(value)
  dbAdd(c.db, c.argv[1], newObj)
 }
 //將累加后的結(jié)果返回給客戶端,按照RESP格式即 :數(shù)值\r\n,例如返回10 那么格式就是:10\r\n
 reply := *shared.colon + strconv.FormatInt(value, 10) + *shared.crlf
 addReply(c, &reply)

}

遞增遞減的復(fù)用

基于上述函數(shù)對(duì)應(yīng)的遞增指令I(lǐng)NCR就使用incrCommand,入?yún)?代表加1,而decrCommand則傳-1扣減即可:

func incrCommand(c *redisClient) {
 //累加1
 incrDecrCommand(c, 1)
}

func decrCommand(c *redisClient) {
 //遞減1
 incrDecrCommand(c, -1)
}

最終效果演示

最后,我們將服務(wù)啟動(dòng)進(jìn)行測(cè)試,可以看到指令正常執(zhí)行:

127.0.0.1:6379> incr k1
(integer) 1
(4.50s)
127.0.0.1:6379> incr k1
(integer) 2
127.0.0.1:6379> incr k1
(integer) 3
127.0.0.1:6379> incr k1
(integer) 4
127.0.0.1:6379> incr k1
(integer) 5
127.0.0.1:6379> incr k1
(integer) 6
127.0.0.1:6379> decr k1
(integer) 5
127.0.0.1:6379> decr k1
(integer) 4
127.0.0.1:6379> decr k1
(integer) 3
127.0.0.1:6379> decr k1
(integer) 2
127.0.0.1:6379> decr k1
(integer) 1
127.0.0.1:6379> decr k1
(integer) 0
127.0.0.1:6379> decr k1
(integer) -1
127.0.0.1:6379>


責(zé)任編輯:趙寧寧 來(lái)源: 寫(xiě)代碼的SharkChili
相關(guān)推薦

2024-11-22 15:00:00

開(kāi)源Redis鏈表

2018-08-15 09:48:27

數(shù)據(jù)庫(kù)Redis應(yīng)用場(chǎng)景

2023-07-03 07:55:25

2024-04-18 00:20:56

Redis策略數(shù)據(jù)

2024-07-16 08:38:06

2024-04-18 08:00:00

2019-08-06 19:36:25

RedisMemcached緩存

2025-01-15 08:19:12

SpringBootRedis開(kāi)源

2024-07-31 08:33:17

2011-10-25 10:36:19

蘋果臺(tái)式機(jī)

2024-11-11 17:12:22

2024-12-09 00:00:09

2024-10-08 10:13:17

2018-04-27 09:03:57

Redis數(shù)據(jù)存儲(chǔ)

2011-11-07 09:42:58

蘋果臺(tái)式機(jī)

2011-10-27 15:04:19

蘋果臺(tái)式機(jī)

2019-05-17 08:55:49

RedisRDBAOF

2024-09-26 06:30:36

2018-11-06 10:51:07

Redis開(kāi)發(fā)存儲(chǔ)系統(tǒng)

2019-09-16 16:05:13

Redis集群模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

亚洲成年人影院| 欧美日韩在线观看一区二区三区| 日韩三级中文字幕| 日韩av在线网址| 欧美激情亚洲视频| 青青影院一区二区三区四区| 国产欧美高清在线| 亚洲一区免费| 三上悠亚在线观看二区| 欧美xxxx18国产| 国产精品人成在线观看免费| 久久wwww| 九色在线观看| 加勒比成人在线| 国产精品久久久久aaaa九色| 美女爽到高潮91| 99久久伊人| 韩国中文字幕在线| 国产在线观看网站| 被下部羞羞漫画| 黄色三级视频片| 成人视屏免费看| 欧美色图在线播放| jiujiure精品视频播放| 免费精品国产| 欧美日韩黑人| av自拍一区| 视频精品一区二区三区| 91精品啪在线观看国产手机| 日韩精品麻豆| 性国产高清在线观看| 亚洲熟妇av日韩熟妇在线| 大尺度一区二区| 性欧美1819sex性高清大胸| 在线国产福利| 亚洲欧美另类动漫| 久久偷窥视频| 欧美精品videosex极品1| 欧美日韩中文字幕在线视频| 亚洲欧美日韩视频二区| 久久香蕉精品香蕉| 日本资源在线| 天堂中文字幕| 糖心vlog在线免费观看| 亚洲尤物视频网| 国内自拍欧美激情| 色妞欧美日韩在线| 欧美国产精品人人做人人爱| 久久婷婷色综合| av影院午夜一区| 免费在线观看日韩欧美| 国产清纯美女被跳蛋高潮一区二区久久w | 神马午夜久久| 精品久久成人| 欧美国产日韩激情| 黄页网站在线观看| 日韩极品视频在线观看| 一区三区二区视频| igao视频网在线视频| 天堂资源在线中文| 国产一区一区| 久久久久av| 蜜桃av一区二区三区| 亚洲36d大奶网| 亚洲视频欧美在线| 亚洲成人网上| 亚洲a∨一区二区三区| 日韩av大全| 精品视频免费在线播放| 久久这里只精品| 91麻豆一二三四在线| 亚洲精选av| 国语精品一区| 亚洲国产精品黑人久久久| 日韩欧美在线影院| 国产成人在线一区| 亚洲高清视频在线观看| 精品一二三区视频| 香蕉久久精品| 久久久久久久久伊人| 亚洲午夜性刺激影院| 日韩欧美亚洲v片| 能在线观看av网站| 欧美日韩色综合| 国产日产精品1区| 色婷婷国产精品久久包臀 | 国产午夜精品在线观看| 91在线观看免费视频| 色狠狠一区二区| 欧美一性一乱一交一视频| 在线免费一区| 男女免费观看在线爽爽爽视频| 国产探花视频在线观看| 林ゆな中文字幕一区二区| 成人免费三级在线| 亚洲一区二区精品3399| 欧美日韩亚洲另类| 国产精品九九久久久久久久| 欧美 国产 日本| 免费a在线看| 日韩理论电影中文字幕| 26uuu亚洲综合色欧美 | 国产精品全国免费观看高清| 亚洲风情亚aⅴ在线发布| 国产精品电影久久久久电影网| 国产精品va无码一区二区| 欧美激情啪啪| 国产视频久久| 91精品一区二区三区久久久久久| 国产精品尤物福利片在线观看| 日本我和搜子同居的日子高清在线| 日日狠狠久久| 日韩和欧美的一区| 亚洲一二三四久久| 超碰97人人在线| 88xx成人精品| 成人疯狂猛交xxx| h网站在线免费观看| 欧美自拍偷拍| 欧美日韩另类字幕中文| 俄罗斯精品一区二区| 国产日本在线| 麻豆一区二区三| 久热精品视频在线免费观看| 97精品一区二区视频在线观看| 国产精品视频一区二区图片| 亚洲综合图色| 午夜精品久久久久久久| 99porn视频在线| 色综合桃花网| www.亚洲色图.com| 亚洲激情视频网站| 国内成人精品一区| 蜜芽视频在线观看| 999国产精品| 亚洲国产欧美自拍| 国产av熟女一区二区三区| 欧美2区3区4区| 国产欧美日韩久久| 国产精品免费一区二区三区在线观看| 蜜臀国产一区| 亚洲九九爱视频| 欧美日韩国产综合在线| 国产精品男女| 欧美视频一区二区三区四区| 伊人久久大香线蕉综合75| 久久人人视频| 欧美视频一区二区三区在线观看| 人人爽人人av| 在线国产视频观看| 亚洲天堂av资源在线观看| 欧美吻胸吃奶大尺度电影| 一区二区视频国产| 午夜免费啪视频观看视频| 欧美精品国产| 国产美女精彩久久| 国产欧美日韩小视频| 久久精品一区二区三区中文字幕| 国产精品久久久久久久久| 国内精品国产成人国产三级粉色 | 国产精品色呦呦| 国产日韩第一页| 久久99深爱久久99精品| 亚洲日本japanese丝袜| 激情自拍一区| 国产一二三四区在线观看| 国产一区二区三区精品欧美日韩一区二区三区 | 亚洲精品国产系列| 精品成人一区| 成人av在线亚洲| 66久久国产| 欧美一区二区三区成人久久片| 91久久午夜| 国产在线一区二| 国产精品一区二区不卡| 亚洲国产精品久久人人爱| 国产精品久久色| 韩国av一区| 少妇高潮大叫好爽喷水| 成人av资源在线观看| 日本一二区视频| 亚洲午夜久久久久久久久电影网 | 国产精品福利一区二区三区| 久久一区二区精品| 牛牛精品在线| 欧美亚洲免费| 国产热re99久久6国产精品| 黄页网站一区| 日韩三级在线播放| 乡村艳史在线观看| 亚洲成人精品在线| 国产亚洲久久| 国产精品亚洲网站| 日韩国产精品久久久久久亚洲| 亚洲欧美国产精品桃花| 日本一区二区三区视频视频| 瑟瑟在线观看| 亚洲色图美腿丝袜| 久久99国内| 日韩欧美亚洲区|