自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我工作中用Redis的十種場(chǎng)景

數(shù)據(jù)庫(kù) Redis
今天這篇文章就跟大家一起聊聊,我在實(shí)際工作中使用Redis的10種場(chǎng)景,希望對(duì)你會(huì)有所幫助。

前言

Redis作為一種優(yōu)秀的基于key/value的緩存,有非常不錯(cuò)的性能和穩(wěn)定性,無(wú)論是在工作中,還是面試中,都經(jīng)常會(huì)出現(xiàn)。

今天這篇文章就跟大家一起聊聊,我在實(shí)際工作中使用Redis的10種場(chǎng)景,希望對(duì)你會(huì)有所幫助。

1、統(tǒng)計(jì)訪問(wèn)次數(shù)

對(duì)于很多官方網(wǎng)站的首頁(yè),經(jīng)常會(huì)有一些統(tǒng)計(jì)首頁(yè)訪問(wèn)次數(shù)的需求。

訪問(wèn)次數(shù)只有一個(gè)字段,如果保存到數(shù)據(jù)庫(kù)中,再最后做匯總顯然有些麻煩。

該業(yè)務(wù)場(chǎng)景可以使用Redis,定義一個(gè)key,比如:OFFICIAL_INDEX_VISIT_COUNT。

在Redis中有incr命令,可以實(shí)現(xiàn)給value值加1操作:

incr OFFICIAL_INDEX_VISIT_COUNT

當(dāng)然如果你想一次加的值大于1,可以用incrby命令,例如:

incrby OFFICIAL_INDEX_VISIT_COUNT 5

這樣可以一次性加5。

2、獲取分類樹

在很多網(wǎng)站都有分類樹的功能,如果沒(méi)有生成靜態(tài)的html頁(yè)面,想通過(guò)調(diào)用接口的方式獲取分類樹的數(shù)據(jù)。

我們一般為了性能考慮,會(huì)將分類樹的json數(shù)據(jù)緩存到Redis當(dāng)中,為了后面在網(wǎng)站當(dāng)中能夠快速獲取數(shù)據(jù)。

不然在接口中需要使用遞歸查詢數(shù)據(jù)庫(kù),然后拼接成分類樹的數(shù)據(jù)結(jié)構(gòu)。

這個(gè)過(guò)程非常麻煩,而且需要多次查詢數(shù)據(jù)庫(kù),性能很差。

因此,可以考慮用一個(gè)定時(shí)任務(wù),異步將分類樹的數(shù)據(jù),直接緩存到Redis當(dāng)中,定義一個(gè)key,比如:MALL_CATEGORY_TREE。

然后接口中直接使用MALL_CATEGORY_TREE這個(gè)key從緩存中獲取數(shù)據(jù)即可。

可以直接用key/value字符串保存數(shù)據(jù)。

不過(guò)需要注意的是,如果分類樹的數(shù)據(jù)非常多可能會(huì)出現(xiàn)大key的問(wèn)題,優(yōu)化方案可以參考我的另外一篇文章《分類樹,我從2s優(yōu)化到0.1s》。

3、做分布式鎖

分布式鎖可能是使用Redis最常見的場(chǎng)景之一,相對(duì)于其他的分布式鎖,比如:數(shù)據(jù)庫(kù)分布式鎖或者Zookeeper分布式鎖,基于Redis的分布式鎖,有更好的性能,被廣泛使用于實(shí)際工作中。

我們使用下面這段代碼可以加鎖:

try{
  String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
  if ("OK".equals(result)) {
      return true;
  }
  return false;
} finally {
    unlock(lockKey);
}

但上面這段代碼在有些場(chǎng)景下,會(huì)有一些問(wèn)題,釋放鎖可能會(huì)釋放了別人的鎖。

說(shuō)實(shí)話Redis分布式鎖雖說(shuō)很常用,但坑也挺多的,如果用不好的話,很容易踩坑。

4、做排行榜

很多網(wǎng)站有排行榜的功能,比如:商城中有商品銷量的排行榜,游戲網(wǎng)站有玩家獲得積分的排行榜。

通常情況下,我們可以使用Sorted Set保存排行榜的數(shù)據(jù)。

使用ZADD可以添加排行榜的數(shù)據(jù),使用ZRANGE可以獲取排行榜的數(shù)據(jù)。

例如:

ZADD rank:score 100 "周星馳"
ZADD rank:score 90 "周杰倫"
ZADD rank:score 80 "周潤(rùn)發(fā)"
ZRANGE rank:score 0 -1 WITHSCORES

返回?cái)?shù)據(jù):

1) "周星馳"
2) "100"
3) "周杰倫"
4) "90"
5) "周潤(rùn)發(fā)"
6) "80"

5、記錄用戶登錄狀態(tài)

通常下,用戶登錄成功之后,用戶登錄之后的狀態(tài)信息,會(huì)保存到Redis中。

這樣后面該用戶訪問(wèn)其他接口的時(shí)候,會(huì)直接從Redis中查詢用戶登錄狀態(tài),如果可以查到數(shù)據(jù),說(shuō)明用戶已登錄,則允許做后續(xù)的操作。

如果從Redis中沒(méi)有查到用戶登錄狀態(tài),說(shuō)明該用戶沒(méi)有登錄,或者登錄狀態(tài)失效了,則直接跳轉(zhuǎn)到用戶登錄頁(yè)面。

使用Redis保存用戶登錄狀態(tài),有個(gè)好處是它可以設(shè)置一個(gè)過(guò)期時(shí)間,比如:該時(shí)間可以設(shè)置成30分鐘。

jedis.set(userId, userInfo, 1800);

在Redis內(nèi)部有專門的job,會(huì)將過(guò)期的數(shù)據(jù)刪除,也有獲取數(shù)據(jù)時(shí)實(shí)時(shí)刪除的邏輯。

6、限流

使用Redis還有一個(gè)非常常用的的業(yè)務(wù)場(chǎng)景是做限流。

當(dāng)然還有其他的限流方式,比如:使用nginx,但使用Redis控制可以更精細(xì)。

比如:限制同一個(gè)ip,1分鐘之內(nèi)只能訪問(wèn)10次接口,10分鐘之內(nèi)只能訪問(wèn)50次接口,1天之內(nèi)只能訪問(wèn)100次接口。

如果超過(guò)次數(shù),則接口直接返回:請(qǐng)求太頻繁了,請(qǐng)稍后重試。

跟上面保存用戶登錄狀態(tài)類似,需要在Redis中保存用戶的請(qǐng)求記錄。

比如:key是用戶ip,value是訪問(wèn)的次數(shù)從1開始,后面每訪問(wèn)一次則加1。

如果value超過(guò)一定的次數(shù),則直接攔截這種異常的ip。

當(dāng)然也需要設(shè)置一個(gè)過(guò)期時(shí)間,異常ip如果超過(guò)這個(gè)過(guò)期時(shí)間,比如:1天,則恢復(fù)正常了,該ip可以再發(fā)起請(qǐng)求了。

或者限制同一個(gè)用戶id。

7、位統(tǒng)計(jì)

比如現(xiàn)在有個(gè)需求:有個(gè)網(wǎng)站需要統(tǒng)計(jì)一周內(nèi)連續(xù)登陸的用戶,以及一個(gè)月內(nèi)登陸過(guò)的用戶。

這個(gè)需求使用傳統(tǒng)的數(shù)據(jù)庫(kù),實(shí)現(xiàn)起來(lái)比較麻煩,但使用Redis的bitmap讓我們可以實(shí)時(shí)的進(jìn)行類似的統(tǒng)計(jì)。

bitmap 是二進(jìn)制的byte數(shù)組,也可以簡(jiǎn)單理解成是一個(gè)普通字符串。它將二進(jìn)制數(shù)據(jù)存儲(chǔ)在byte數(shù)組中以達(dá)到存儲(chǔ)數(shù)據(jù)的目的。

保存數(shù)據(jù)命令使用setbit,語(yǔ)法:

setbit key offset value

具體示例:

setbit user:view:2024-01-17 123456 1

往bitmap數(shù)組中設(shè)置了用戶id=123456的登錄狀態(tài)為1,標(biāo)記2024-01-17已登錄。

然后通過(guò)命令getbit獲取數(shù)據(jù),語(yǔ)法:

getbit key offset

具體示例:

getbit user:view:2024-01-17 123456

如果獲取的值是1,說(shuō)明這一天登錄了。

如果我們想統(tǒng)計(jì)一周內(nèi)連續(xù)登錄的用戶,只需要遍歷用戶id,根據(jù)日期中數(shù)組中去查詢狀態(tài)即可。

8、緩存加速

我們?cè)诠ぷ髦惺褂肦edis作為緩存加速,這種用法也是非常常見的。

如果查詢訂單數(shù)據(jù),先從Redis緩存中查詢,如果緩存中存在,則直接將數(shù)據(jù)返回給用戶。

如果緩存中不存在,則再?gòu)臄?shù)據(jù)庫(kù)中查詢數(shù)據(jù),如果數(shù)據(jù)存在,則將數(shù)據(jù)保存到緩存中,然后再返回給用戶。

如果緩存和數(shù)據(jù)庫(kù)都不存在,則直接給用戶返回?cái)?shù)據(jù)不存在。

流程圖如下:

但使用緩存加速的業(yè)務(wù)場(chǎng)景,需要注意一下,可能會(huì)出現(xiàn):緩存擊穿、穿透和雪崩等問(wèn)題。

9、做消息隊(duì)列

我們說(shuō)起隊(duì)列經(jīng)常想到是:kafka、rabbitMQ、RocketMQ等這些分布式消息隊(duì)列。

其實(shí)Redis也有消息隊(duì)列的功能,我們之前有個(gè)支付系統(tǒng),就是用的Redis隊(duì)列功能。

PubSub(發(fā)布訂閱)是Redis2.0版本引入的消息傳遞模型。

顧名思義,消費(fèi)者可以訂閱一個(gè)或多個(gè)channel,生產(chǎn)者向?qū)?yīng)channel發(fā)送消息后,所有訂閱者都能收到相關(guān)消息。對(duì)應(yīng)channel發(fā)送消息后,所有訂閱者都能收到相關(guān)消息。

在java代碼中可以實(shí)現(xiàn)MessageListener接口,來(lái)消費(fèi)隊(duì)列中的消息。

@Slf4j
@Component
public class RedisMessageListenerListener implements MessageListener {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String channel = new String(pattern);
        RedisSerializer<?> valueSerializer = redisTemplate.getValueSerializer();
        Object deserialize = valueSerializer.deserialize(message.getBody());
        if (deserialize == null) return;
        String md5DigestAsHex = DigestUtils.md5DigestAsHex(deserialize.toString().getBytes(StandardCharsets.UTF_8));
        Boolean result = redisTemplate.opsForValue().setIfAbsent(md5DigestAsHex, "1", 20, TimeUnit.SECONDS);
        if (Boolean.TRUE.equals(result)) {
            log.info("接收的結(jié)果:{}", deserialize.toString());
        } else {
            log.info("其他服務(wù)處理中");
        }
    }
}

10、生成全局ID

在有些需要生成全局ID的業(yè)務(wù)場(chǎng)景,其實(shí)也可以使用Redis。

可以使用incrby命令,利用原子性操作,可以執(zhí)行下面這個(gè)命令:

incrby userid 10000

在分庫(kù)分表的場(chǎng)景,對(duì)于有些批量操作,我們可以從Redis中,一次性拿一批id出來(lái),然后給業(yè)務(wù)系統(tǒng)使用。

責(zé)任編輯:姜華 來(lái)源: 蘇三說(shuō)技術(shù)
相關(guān)推薦

2024-02-28 07:53:30

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

2024-04-15 00:10:00

Redis數(shù)據(jù)庫(kù)

2018-09-25 23:21:13

2024-11-25 09:08:10

Redis高頻應(yīng)用場(chǎng)景

2022-01-09 18:32:03

MySQL SQL 語(yǔ)句數(shù)據(jù)庫(kù)

2025-02-10 08:30:00

JavaScrip開發(fā)設(shè)計(jì)模式

2015-12-09 09:41:52

AngularJS開發(fā)錯(cuò)誤

2023-02-08 13:07:54

2015-10-26 09:38:23

程序員工作

2024-11-13 13:20:44

2023-05-15 15:29:13

設(shè)計(jì)模式JavaScript

2024-08-22 08:54:40

2010-07-07 11:30:16

UML十種圖

2020-08-13 07:00:00

工具技術(shù)管理

2010-08-30 16:18:05

2010-09-13 17:17:04

2024-01-22 08:15:42

API協(xié)議設(shè)計(jì)

2023-05-15 20:08:04

Linux字體

2019-08-15 14:11:31

LVS負(fù)載均衡調(diào)度算法

2010-09-07 13:12:17

點(diǎn)贊
收藏

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