国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

redis 應(yīng)用 4: HyperLogLog

這篇具有很好參考價(jià)值的文章主要介紹了redis 應(yīng)用 4: HyperLogLog。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

我們先思考一個(gè)常見的業(yè)務(wù)問題:如果你負(fù)責(zé)開發(fā)維護(hù)一個(gè)大型的網(wǎng)站,有一天老板找產(chǎn)品經(jīng)理要網(wǎng)站每個(gè)網(wǎng)頁每天的 UV 數(shù)據(jù),然后讓你來開發(fā)這個(gè)統(tǒng)計(jì)模塊,你會(huì)如何實(shí)現(xiàn)?

img

如果統(tǒng)計(jì) PV 那非常好辦,給每個(gè)網(wǎng)頁一個(gè)獨(dú)立的 Redis 計(jì)數(shù)器就可以了,這個(gè)計(jì)數(shù)器的 key 后綴加上當(dāng)天的日期。這樣來一個(gè)請(qǐng)求,incrby 一次,最終就可以統(tǒng)計(jì)出所有的 PV 數(shù)據(jù)。

但是 UV 不一樣,它要去重,同一個(gè)用戶一天之內(nèi)的多次訪問請(qǐng)求只能計(jì)數(shù)一次。這就要求每一個(gè)網(wǎng)頁請(qǐng)求都需要帶上用戶的 ID,無論是登陸用戶還是未登陸用戶都需要一個(gè)唯一 ID 來標(biāo)識(shí)。

你也許已經(jīng)想到了一個(gè)簡單的方案,那就是為每一個(gè)頁面一個(gè)獨(dú)立的 set 集合來存儲(chǔ)所有當(dāng)天訪問過此頁面的用戶 ID。當(dāng)一個(gè)請(qǐng)求過來時(shí),我們使用 sadd 將用戶 ID 塞進(jìn)去就可以了。通過 scard 可以取出這個(gè)集合的大小,這個(gè)數(shù)字就是這個(gè)頁面的 UV 數(shù)據(jù)。沒錯(cuò),這是一個(gè)非常簡單的方案。

但是,如果你的頁面訪問量非常大,比如一個(gè)爆款頁面幾千萬的 UV,你需要一個(gè)很大的 set 集合來統(tǒng)計(jì),這就非常浪費(fèi)空間。如果這樣的頁面很多,那所需要的存儲(chǔ)空間是驚人的。為這樣一個(gè)去重功能就耗費(fèi)這樣多的存儲(chǔ)空間,值得么?其實(shí)老板需要的數(shù)據(jù)又不需要太精確,105w 和 106w 這兩個(gè)數(shù)字對(duì)于老板們來說并沒有多大區(qū)別,So,有沒有更好的解決方案呢?

這就是本節(jié)要引入的一個(gè)解決方案,Redis 提供了 HyperLogLog 數(shù)據(jù)結(jié)構(gòu)就是用來解決這種統(tǒng)計(jì)問題的。HyperLogLog 提供不精確的去重計(jì)數(shù)方案,雖然不精確但是也不是非常不精確,標(biāo)準(zhǔn)誤差是 0.81%,這樣的精確度已經(jīng)可以滿足上面的 UV 統(tǒng)計(jì)需求了。

HyperLogLog 數(shù)據(jù)結(jié)構(gòu)是 Redis 的高級(jí)數(shù)據(jù)結(jié)構(gòu),它非常有用,但是令人感到意外的是,使用過它的人非常少。

使用方法

HyperLogLog 提供了兩個(gè)指令 pfadd 和 pfcount,根據(jù)字面意義很好理解,一個(gè)是增加計(jì)數(shù),一個(gè)是獲取計(jì)數(shù)。pfadd 用法和 set 集合的 sadd 是一樣的,來一個(gè)用戶 ID,就將用戶 ID 塞進(jìn)去就是。pfcount 和 scard 用法是一樣的,直接獲取計(jì)數(shù)值。

bash復(fù)制代碼127.0.0.1:6379>?pfadd?codehole?user1
(integer)?1
127.0.0.1:6379>?pfcount?codehole
(integer)?1
127.0.0.1:6379>?pfadd?codehole?user2
(integer)?1
127.0.0.1:6379>?pfcount?codehole
(integer)?2
127.0.0.1:6379>?pfadd?codehole?user3
(integer)?1
127.0.0.1:6379>?pfcount?codehole
(integer)?3
127.0.0.1:6379>?pfadd?codehole?user4
(integer)?1
127.0.0.1:6379>?pfcount?codehole
(integer)?4
127.0.0.1:6379>?pfadd?codehole?user5
(integer)?1
127.0.0.1:6379>?pfcount?codehole
(integer)?5
127.0.0.1:6379>?pfadd?codehole?user6
(integer)?1
127.0.0.1:6379>?pfcount?codehole
(integer)?6
127.0.0.1:6379>?pfadd?codehole?user7?user8?user9?user10
(integer)?1
127.0.0.1:6379>?pfcount?codehole
(integer)?10

簡單試了一下,發(fā)現(xiàn)還蠻精確的,一個(gè)沒多也一個(gè)沒少。接下來我們使用腳本,往里面灌更多的數(shù)據(jù),看看它是否還可以繼續(xù)精確下去,如果不能精確,差距有多大。人生苦短,我用 Python!Python 腳本走起來!??

py復(fù)制代碼#?coding:?utf-8

import?redis

client?=?redis.StrictRedis()
for?i?in?range(1000):
????client.pfadd("codehole",?"user%d"?%?i)
????total?=?client.pfcount("codehole")
????if?total?!=?i+1:
????????print?total,?i+1
????????break

當(dāng)然 Java 也不錯(cuò),大同小異,下面是 Java 版本:

java復(fù)制代碼public?class?PfTest?{
??public?static?void?main(String[]?args)?{
????Jedis?jedis?=?new?Jedis();
????for?(int?i?=?0;?i?<?1000;?i++)?{
??????jedis.pfadd("codehole",?"user"?+?i);
??????long?total?=?jedis.pfcount("codehole");
??????if?(total?!=?i?+?1)?{
????????System.out.printf("%d?%d\n",?total,?i?+?1);
????????break;
??????}
????}
????jedis.close();
??}
}

我們來看下輸出:

markdown復(fù)制代碼>?python?pftest.py
99?100

當(dāng)我們加入第 100 個(gè)元素時(shí),結(jié)果開始出現(xiàn)了不一致。接下來我們將數(shù)據(jù)增加到 10w 個(gè),看看總量差距有多大。

css復(fù)制代碼#?coding:?utf-8

import?redis

client?=?redis.StrictRedis()
for?i?in?range(100000):
????client.pfadd("codehole",?"user%d"?%?i)
print?100000,?client.pfcount("codehole")

Java 版:

java復(fù)制代碼public?class?JedisTest?{
??public?static?void?main(String[]?args)?{
????Jedis?jedis?=?new?Jedis();
????for?(int?i?=?0;?i?<?100000;?i++)?{
??????jedis.pfadd("codehole",?"user"?+?i);
????}
????long?total?=?jedis.pfcount("codehole");
????System.out.printf("%d?%d\n",?100000,?total);
????jedis.close();
??}
}

跑了約半分鐘,我們看輸出:

markdown復(fù)制代碼>?python?pftest.py
100000?99723

差了 277 個(gè),按百分比是 0.277%,對(duì)于上面的 UV 統(tǒng)計(jì)需求來說,誤差率也不算高。然后我們把上面的腳本再跑一邊,也就相當(dāng)于將數(shù)據(jù)重復(fù)加入一邊,查看輸出,可以發(fā)現(xiàn),pfcount 的結(jié)果沒有任何改變,還是 99723,說明它確實(shí)具備去重功能。

pfadd 這個(gè) pf 是什么意思?

它是 HyperLogLog 這個(gè)數(shù)據(jù)結(jié)構(gòu)的發(fā)明人 Philippe Flajolet 的首字母縮寫,老師覺得他發(fā)型很酷,看起來是個(gè)佛系教授。

redis 應(yīng)用 4: HyperLogLog,后端
img

pfmerge 適合什么場合用?

HyperLogLog 除了上面的 pfadd 和 pfcount 之外,還提供了第三個(gè)指令 pfmerge,用于將多個(gè) pf 計(jì)數(shù)值累加在一起形成一個(gè)新的 pf 值。

比如在網(wǎng)站中我們有兩個(gè)內(nèi)容差不多的頁面,運(yùn)營說需要這兩個(gè)頁面的數(shù)據(jù)進(jìn)行合并。其中頁面的 UV 訪問量也需要合并,那這個(gè)時(shí)候 pfmerge 就可以派上用場了。

注意事項(xiàng)

HyperLogLog 這個(gè)數(shù)據(jù)結(jié)構(gòu)不是免費(fèi)的,不是說使用這個(gè)數(shù)據(jù)結(jié)構(gòu)要花錢,它需要占據(jù)一定 12k 的存儲(chǔ)空間,所以它不適合統(tǒng)計(jì)單個(gè)用戶相關(guān)的數(shù)據(jù)。如果你的用戶上億,可以算算,這個(gè)空間成本是非常驚人的。但是相比 set 存儲(chǔ)方案,HyperLogLog 所使用的空間那真是可以使用千斤對(duì)比四兩來形容了。

不過你也不必過于擔(dān)心,因?yàn)?Redis 對(duì) HyperLogLog 的存儲(chǔ)進(jìn)行了優(yōu)化,在計(jì)數(shù)比較小時(shí),它的存儲(chǔ)空間采用稀疏矩陣存儲(chǔ),空間占用很小,僅僅在計(jì)數(shù)慢慢變大,稀疏矩陣占用空間漸漸超過了閾值時(shí)才會(huì)一次性轉(zhuǎn)變成稠密矩陣,才會(huì)占用 12k 的空間。

HyperLogLog 實(shí)現(xiàn)原理

HyperLogLog 的使用非常簡單,但是實(shí)現(xiàn)原理比較復(fù)雜,如果讀者沒有特別的興趣,下面的內(nèi)容暫時(shí)可以跳過不看。

為了方便理解 HyperLogLog 的內(nèi)部實(shí)現(xiàn)原理,我畫了下面這張圖

redis 應(yīng)用 4: HyperLogLog,后端
img

這張圖的意思是,給定一系列的隨機(jī)整數(shù),我們記錄下低位連續(xù)零位的最大長度 k,通過這個(gè) k 值可以估算出隨機(jī)數(shù)的數(shù)量。 首先不問為什么,我們編寫代碼做一個(gè)實(shí)驗(yàn),觀察一下隨機(jī)整數(shù)的數(shù)量和 k 值的關(guān)系。

py復(fù)制代碼import?math
import?random

#?算低位零的個(gè)數(shù)
def?low_zeros(value):
????for?i?in?xrange(1,?32):
????????if?value?>>?i?<<?i?!=?value:
????????????break
????return?i?-?1


#?通過隨機(jī)數(shù)記錄最大的低位零的個(gè)數(shù)
class?BitKeeper(object):

????def?__init__(self):
????????self.maxbits?=?0

????def?random(self):
????????value?=?random.randint(0,?2**32-1)
????????bits?=?low_zeros(value)
????????if?bits?>?self.maxbits:
????????????self.maxbits?=?bits


class?Experiment(object):

????def?__init__(self,?n):
????????self.n?=?n
????????self.keeper?=?BitKeeper()

????def?do(self):
????????for?i?in?range(self.n):
????????????self.keeper.random()

????def?debug(self):
????????print?self.n,?'%.2f'?%?math.log(self.n,?2),?self.keeper.maxbits


for?i?in?range(1000,?100000,?100):
????exp?=?Experiment(i)
????exp.do()
????exp.debug()

Java 版:

java復(fù)制代碼public?class?PfTest?{

??static?class?BitKeeper?{
????private?int?maxbits;

????public?void?random()?{
??????long?value?=?ThreadLocalRandom.current().nextLong(2L?<<?32);
??????int?bits?=?lowZeros(value);
??????if?(bits?>?this.maxbits)?{
????????this.maxbits?=?bits;
??????}
????}

????private?int?lowZeros(long?value)?{
??????int?i?=?1;
??????for?(;?i?<?32;?i++)?{
????????if?(value?>>?i?<<?i?!=?value)?{
??????????break;
????????}
??????}
??????return?i?-?1;
????}
??}

??static?class?Experiment?{
????private?int?n;
????private?BitKeeper?keeper;

????public?Experiment(int?n)?{
??????this.n?=?n;
??????this.keeper?=?new?BitKeeper();
????}

????public?void?work()?{
??????for?(int?i?=?0;?i?<?n;?i++)?{
????????this.keeper.random();
??????}
????}

????public?void?debug()?{
??????System.out.printf("%d?%.2f?%d\n",?this.n,?Math.log(this.n)?/?Math.log(2),?this.keeper.maxbits);
????}
??}

??public?static?void?main(String[]?args)?{
????for?(int?i?=?1000;?i?<?100000;?i?+=?100)?{
??????Experiment?exp?=?new?Experiment(i);
??????exp.work();
??????exp.debug();
????}
??}

}

運(yùn)行觀察輸出:

復(fù)制代碼36400?15.15?13
36500?15.16?16
36600?15.16?13
36700?15.16?14
36800?15.17?15
36900?15.17?18
37000?15.18?16
37100?15.18?15
37200?15.18?13
37300?15.19?14
37400?15.19?16
37500?15.19?14
37600?15.20?15

通過這實(shí)驗(yàn)可以發(fā)現(xiàn) K 和 N 的對(duì)數(shù)之間存在顯著的線性相關(guān)性:

ini
復(fù)制代碼N=2^K  # 約等于

如果 N 介于 2^K 和 2^(K+1) 之間,用這種方式估計(jì)的值都等于 2^K,這明顯是不合理的。這里可以采用多個(gè) BitKeeper,然后進(jìn)行加權(quán)估計(jì),就可以得到一個(gè)比較準(zhǔn)確的值。

py復(fù)制代碼import?math
import?random

def?low_zeros(value):
????for?i?in?xrange(1,?32):
????????if?value?>>?i?<<?i?!=?value:
????????????break
????return?i?-?1


class?BitKeeper(object):

????def?__init__(self):
????????self.maxbits?=?0

????def?random(self,?m):
????????bits?=?low_zeros(m)
????????if?bits?>?self.maxbits:
????????????self.maxbits?=?bits


class?Experiment(object):

????def?__init__(self,?n,?k=1024):
????????self.n?=?n
????????self.k?=?k
????????self.keepers?=?[BitKeeper()?for?i?in?range(k)]

????def?do(self):
????????for?i?in?range(self.n):
????????????m?=?random.randint(0,?1<<32-1)
????????????#?確保同一個(gè)整數(shù)被分配到同一個(gè)桶里面,摘取高位后取模
????????????keeper?=?self.keepers[((m?&?0xfff0000)?>>?16)?%?len(self.keepers)]
????????????keeper.random(m)

????def?estimate(self):
????????sumbits_inverse?=?0??#?零位數(shù)倒數(shù)
????????for?keeper?in?self.keepers:
????????????sumbits_inverse?+=?1.0/float(keeper.maxbits)
????????avgbits?=?float(self.k)/sumbits_inverse??#?平均零位數(shù)
????????return?2**avgbits?*?self.k??#?根據(jù)桶的數(shù)量對(duì)估計(jì)值進(jìn)行放大


for?i?in?range(100000,?1000000,?100000):
????exp?=?Experiment(i)
????exp.do()
????est?=?exp.estimate()
????print?i,?'%.2f'?%?est,?'%.2f'?%?(abs(est-i)?/?i)

下面是 Java 版:

java復(fù)制代碼public?class?PfTest?{

??static?class?BitKeeper?{
????private?int?maxbits;

????public?void?random(long?value)?{
??????int?bits?=?lowZeros(value);
??????if?(bits?>?this.maxbits)?{
????????this.maxbits?=?bits;
??????}
????}

????private?int?lowZeros(long?value)?{
??????int?i?=?1;
??????for?(;?i?<?32;?i++)?{
????????if?(value?>>?i?<<?i?!=?value)?{
??????????break;
????????}
??????}
??????return?i?-?1;
????}
??}

??static?class?Experiment?{
????private?int?n;
????private?int?k;
????private?BitKeeper[]?keepers;

????public?Experiment(int?n)?{
??????this(n,?1024);
????}

????public?Experiment(int?n,?int?k)?{
??????this.n?=?n;
??????this.k?=?k;
??????this.keepers?=?new?BitKeeper[k];
??????for?(int?i?=?0;?i?<?k;?i++)?{
????????this.keepers[i]?=?new?BitKeeper();
??????}
????}

????public?void?work()?{
??????for?(int?i?=?0;?i?<?this.n;?i++)?{
????????long?m?=?ThreadLocalRandom.current().nextLong(1L?<<?32);
????????BitKeeper?keeper?=?keepers[(int)?(((m?&?0xfff0000)?>>?16)?%?keepers.length)];
????????keeper.random(m);
??????}
????}

????public?double?estimate()?{
??????double?sumbitsInverse?=?0.0;
??????for?(BitKeeper?keeper?:?keepers)?{
????????sumbitsInverse?+=?1.0?/?(float)?keeper.maxbits;
??????}
??????double?avgBits?=?(float)?keepers.length?/?sumbitsInverse;
??????return?Math.pow(2,?avgBits)?*?this.k;
????}
??}

??public?static?void?main(String[]?args)?{
????for?(int?i?=?100000;?i?<?1000000;?i?+=?100000)?{
??????Experiment?exp?=?new?Experiment(i);
??????exp.work();
??????double?est?=?exp.estimate();
??????System.out.printf("%d?%.2f?%.2f\n",?i,?est,?Math.abs(est?-?i)?/?i);
????}
??}

}

代碼中分了 1024 個(gè)桶,計(jì)算平均數(shù)使用了調(diào)和平均 (倒數(shù)的平均)。普通的平均法可能因?yàn)閭€(gè)別離群值對(duì)平均結(jié)果產(chǎn)生較大的影響,調(diào)和平均可以有效平滑離群值的影響。

redis 應(yīng)用 4: HyperLogLog,后端
img

觀察腳本的輸出,誤差率控制在百分比個(gè)位數(shù):

復(fù)制代碼100000?97287.38?0.03
200000?189369.02?0.05
300000?287770.04?0.04
400000?401233.52?0.00
500000?491704.97?0.02
600000?604233.92?0.01
700000?721127.67?0.03
800000?832308.12?0.04
900000?870954.86?0.03
1000000?1075497.64?0.08

真實(shí)的 HyperLogLog 要比上面的示例代碼更加復(fù)雜一些,也更加精確一些。上面的這個(gè)算法在隨機(jī)次數(shù)很少的情況下會(huì)出現(xiàn)除零錯(cuò)誤,因?yàn)?maxbits=0 是不可以求倒數(shù)的。

pf 的內(nèi)存占用為什么是 12k?

我們在上面的算法中使用了 1024 個(gè)桶進(jìn)行獨(dú)立計(jì)數(shù),不過在 Redis 的 HyperLogLog 實(shí)現(xiàn)中用到的是 16384 個(gè)桶,也就是 2^14,每個(gè)桶的 maxbits 需要 6 個(gè) bits 來存儲(chǔ),最大可以表示 maxbits=63,于是總共占用內(nèi)存就是2^14 * 6 / 8 = 12k字節(jié)。

本文由 mdnice 多平臺(tái)發(fā)布文章來源地址http://www.zghlxwxcb.cn/news/detail-684426.html

到了這里,關(guān)于redis 應(yīng)用 4: HyperLogLog的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 深入學(xué)習(xí) redis - Stream、Geospatial、HyperLogLog、Bitmap、Bitfields 類型擴(kuò)展

    深入學(xué)習(xí) redis - Stream、Geospatial、HyperLogLog、Bitmap、Bitfields 類型擴(kuò)展

    目錄 前言 Stream geospatial HyperLogLog Bitmaps Bitfields redis 中最關(guān)鍵的五個(gè)數(shù)據(jù)類型 String、List、Hash、Set、Zset 應(yīng)用最廣泛,同時(shí) redis 也推出了額外的 5 個(gè)數(shù)據(jù)類型,他們分別是針對(duì)特殊場景才進(jìn)行的應(yīng)用的. Ps:這幾種類型的具體使用不用記,記你也記不住,因?yàn)椴怀S?,因此我?/p>

    2024年02月15日
    瀏覽(43)
  • redis7高級(jí)篇3 數(shù)據(jù)量億級(jí)別的統(tǒng)計(jì)分析(hyperloglog,bitmap,geo)

    redis7高級(jí)篇3 數(shù)據(jù)量億級(jí)別的統(tǒng)計(jì)分析(hyperloglog,bitmap,geo)

    1.聚合統(tǒng)計(jì):統(tǒng)計(jì)多個(gè)集合聚合的結(jié)果,也就是多個(gè)集合之間交并差的統(tǒng)計(jì)。 2.排序統(tǒng)計(jì):在需要展示最新列表,排行榜等場景時(shí),如果數(shù)據(jù)更新頻繁或者需要分頁時(shí),建議使用zset127.0.0.1:6379 zadd pl ?111222 beijing 111223 tianjing 111333 shanghai (integer) 3 127.0.0.1:6379 zrange pl 0 1 1) \\\"beijin

    2024年02月11日
    瀏覽(40)
  • JAVA面試部分——后端-Redis

    6.1 為什么要使用Redis? Redis(Remote Dictionary Server)是一個(gè)開源的內(nèi)存數(shù)據(jù)存儲(chǔ)系統(tǒng),它可以用作數(shù)據(jù)庫、緩存和消息中間件。以下是一些使用Redis的主要優(yōu)勢: 快速讀寫操作: Redis是基于內(nèi)存的存儲(chǔ)系統(tǒng),因此能夠提供非常快速的讀寫操作。它將數(shù)據(jù)存儲(chǔ)在內(nèi)存中,而不是磁

    2024年01月22日
    瀏覽(21)
  • 后端開發(fā)5.Redis的搭建

    使用 docker安裝 Redis【redis】(6379) 拉取Redis鏡像 啟動(dòng)Redis容器 啟動(dòng)Redis容器并設(shè)置密碼 測試redis是否啟動(dòng)成功,我們可以找一個(gè)本地redis,運(yùn)行命令: 啟動(dòng)redis客戶端 ?

    2024年02月13日
    瀏覽(13)
  • 后端項(xiàng)目開發(fā):整合redis緩存

    因?yàn)楦鞣N場合比如門戶和后臺(tái),需要不同的redis配置,我們在common包配置通用的reids配置。 1.新建service目錄,建立RedisService服務(wù)接口,同時(shí)編寫工具類實(shí)現(xiàn)該接口。 2.在config目錄下,編寫redis通用配置 3.其他包只需要繼承該基礎(chǔ)配置就夠了

    2024年02月11日
    瀏覽(22)
  • 自學(xué)WEB后端05-Node.js后端服務(wù)鏈接數(shù)據(jù)庫redis

    自學(xué)WEB后端05-Node.js后端服務(wù)鏈接數(shù)據(jù)庫redis

    嘿,親愛的小伙伴們!?? 今天我要給大家分享一個(gè)超級(jí)方便且高效的 NoSQL 類型數(shù)據(jù)庫——Redis!?? 它可不是一般的關(guān)系型數(shù)據(jù)庫哦,而是以鍵值對(duì)形式存儲(chǔ)數(shù)據(jù)的內(nèi)存數(shù)據(jù)庫。?? 快跟著我一起來學(xué)習(xí)如何安裝和使用 Redis 吧!? 自學(xué)WEB后端01-安裝Express+Node.js框架完成Hello

    2024年02月07日
    瀏覽(34)
  • Java后端開發(fā)面試題篇——Redis

    Java后端開發(fā)面試題篇——Redis

    Redis的數(shù)據(jù)持久化策略有哪些 RDB的執(zhí)行原理? bgsave開始時(shí)會(huì)fork主進(jìn)程得到子進(jìn)程,子進(jìn)程共享主進(jìn)程的內(nèi)存數(shù)據(jù)。完成fork后讀取內(nèi)存數(shù)據(jù)并寫入 RDB 文件。 fork采用的是copy-on-write技術(shù): 當(dāng)主進(jìn)程執(zhí)行讀操作時(shí),訪問共享內(nèi)存; 當(dāng)主進(jìn)程執(zhí)行寫操作時(shí),則會(huì)拷貝一份數(shù)據(jù),執(zhí)

    2024年02月12日
    瀏覽(23)
  • 【后端那些事兒】Redis設(shè)計(jì)與實(shí)現(xiàn)(一) 數(shù)據(jù)結(jié)構(gòu),耐心看完你比Redis還懂Redis!

    【后端那些事兒】Redis設(shè)計(jì)與實(shí)現(xiàn)(一) 數(shù)據(jù)結(jié)構(gòu),耐心看完你比Redis還懂Redis!

    本文章主要為了幫助讀者認(rèn)識(shí)Redis的數(shù)據(jù)結(jié)構(gòu),并深入了解Redis的數(shù)據(jù)結(jié)構(gòu),創(chuàng)作不易,希望得到大家的點(diǎn)贊、收藏、關(guān)注!謝謝! 1.1簡單動(dòng)態(tài)字符串(SDS)的定義 Redis的簡單動(dòng)態(tài)字符串(Simple Dynamic String,SDS)是Redis內(nèi)部使用的字符串表示方式。SDS是一種可以自動(dòng)擴(kuò)展長度的字

    2024年01月22日
    瀏覽(21)
  • 第一次后端復(fù)習(xí)整理(JVM、Redis、反射)

    第一次后端復(fù)習(xí)整理(JVM、Redis、反射)

    文章僅為自身筆記 詳情查看一篇文章掌握整個(gè)JVM,JVM超詳細(xì)解析?。。?jvm是Java虛擬機(jī) 程序員編寫代碼形成.java文件 經(jīng)過javac編譯成.class文件 再通過JVM的類加載器進(jìn)入運(yùn)行時(shí)數(shù)據(jù)區(qū) 就是我們java運(yùn)行時(shí)的東西的存放區(qū)域 其中分為五個(gè)模塊 線程共享的: 方法區(qū) 堆 線程私有的

    2024年02月15日
    瀏覽(16)
  • springboot實(shí)現(xiàn)后端防重復(fù)提交(AOP+redis分布式鎖)單機(jī)情況下

    springboot實(shí)現(xiàn)后端防重復(fù)提交(AOP+redis分布式鎖)單機(jī)情況下

    為什么要實(shí)現(xiàn)這個(gè)功能呢,可能用戶在提交一份數(shù)據(jù)后,可能因?yàn)榫W(wǎng)絡(luò)的原因、處理數(shù)據(jù)的速度慢等原因?qū)е马撁鏇]有及時(shí)將用戶剛提交數(shù)據(jù)的后臺(tái)處理結(jié)果展示給用戶,這時(shí)用戶可能會(huì)進(jìn)行如下操作: 1秒內(nèi)連續(xù)點(diǎn)擊提交按鈕,導(dǎo)致重復(fù)提交表單。 使用瀏覽器后退按鈕重復(fù)之

    2024年02月08日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包