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

分享一個(gè)網(wǎng)上搜不到的「Redis」實(shí)現(xiàn)「聊天回合制」的方案

開發(fā)
分享出來大家可以收藏,萬一你哪天也碰到這樣的需求,可不就節(jié)省大把時(shí)間了嗎。

前言

為什么說網(wǎng)上搜不到,因?yàn)殛P(guān)于聊天回合制的方案作者本人快把百度搜禿嚕了也沒找到,好在最終是公司一個(gè)關(guān)系不錯(cuò)的大佬幫提供了點(diǎn)思路,最終作者將其完整實(shí)現(xiàn)了出來。

分享出來大家可以收藏,萬一你哪天也碰到這樣的需求,可不就節(jié)省大把時(shí)間了嗎。

場景

先說下我這邊的場景,讀過我文章的同好都知道,我是做互聯(lián)網(wǎng)醫(yī)療行業(yè)的,我們的項(xiàng)目中是包含聊天功能的,我們服務(wù)的對象主要是醫(yī)院的醫(yī)生,患者在網(wǎng)上找醫(yī)生問診時(shí),往往會出現(xiàn)不停問的情況。

醫(yī)生目前唯一的做法是自己結(jié)束這個(gè)咨詢,或等待系統(tǒng)自動(dòng)結(jié)束,這就帶來了一個(gè)問題,不管是系統(tǒng)結(jié)束還是醫(yī)生手動(dòng)結(jié)束,患者都喜歡投訴和打差評,導(dǎo)致醫(yī)生不敢擅自結(jié)束,問煩了又不好不回復(fù),不回復(fù)也要被投訴。

最終聊天回合制這個(gè)需求就擺出來了,主動(dòng)告訴患者我們的聊天是有回合的,所以你要一次問清楚,回合數(shù)滿了我們不會再回復(fù),如果患者硬要投訴,醫(yī)生也可以說,這是做這個(gè)產(chǎn)品的公司自己設(shè)定的。

結(jié)下來就是,我們要把鍋端好。

實(shí)際上,聊天回合制的誕生,基本上都和這個(gè)場景的訴求類似,為了減少用戶頻繁且無休止的咨詢。

思路

結(jié)合redis能夠很好的實(shí)現(xiàn)聊天回合制,當(dāng)然也可以直接通過數(shù)據(jù)庫來實(shí)現(xiàn),但顯然redis操作更簡單性能更優(yōu)越。

總體思路如下:

1)redis中存儲兩個(gè)key,一個(gè)是表示對象,聲明為chat-who:consultId,value為對象標(biāo)識,比如這里就是醫(yī)生和患者,醫(yī)生用D標(biāo)識,患者用P標(biāo)識;另一個(gè)key是表示回合數(shù),聲明為chat-num:consultId,value就是當(dāng)前回合數(shù)。這里的consultId是動(dòng)態(tài)的,表示這個(gè)咨詢的id,可以根據(jù)自己的業(yè)務(wù)來定;

2)這兩個(gè)key的過期時(shí)間我們都定為2天,具體過期時(shí)間要根據(jù)自己業(yè)務(wù)規(guī)則來適配;

3)我們在特定的位置進(jìn)行初始化,只要是進(jìn)入聊天之前都可以,比如這里的場景,就是患者發(fā)起咨詢成功后才開始聊天,我們就在發(fā)起成功后的方法中初始化聊天回合數(shù)為默認(rèn)值6個(gè)回合,這個(gè)默認(rèn)值還可以做成配置的形式進(jìn)行動(dòng)態(tài)讀取的;

4)我們在發(fā)消息的方法中做一個(gè)判斷,獲取redis中的chat-who:consultId,看是否存在,存在就往下執(zhí)行,不存在就說明發(fā)的是第一條消息,那就創(chuàng)建chat-who:consultId這個(gè)key到redis中,value為當(dāng)前發(fā)消息人D或者P;

5)、承接4,如果chat-who存在,我們繼續(xù) 將當(dāng)前發(fā)消息的對象和redis的chat-who存儲的對象值進(jìn)行比較,如果一樣,則跳過不管,如果不一樣,更新chat-who的值為當(dāng)前發(fā)消息的人。同時(shí),我們判斷當(dāng)前發(fā)消息的人是不是醫(yī)生也就是D,是D的話才更新回合數(shù),執(zhí)行-1操作 ,這樣做的目的是把醫(yī)生作為回合數(shù)更新的維度,維度只能有一個(gè),這樣才能保證回合數(shù)更新最準(zhǔn)確。

實(shí)現(xiàn)

接下來,我使用偽代碼把整個(gè)思路寫出來。

1、定義redis-key

/**
* 聊天回合制常量
*/
public final class ChatRoundConstants {
/**
* 聊天回合數(shù)key前綴
*/
public static final String CHAT_NUM = "chat-num:";
/**
* 聊天對象key前綴
*/
public static final String CHAT_WHO = "chat-who:";
/**
* redis-key過期時(shí)間
*/
public static final Long EXPIRE_TIME = 48 * 3600L;
/**
* 聊天對象value值,醫(yī)生-D,患者-P。
*/
public static final String DOCTOR = "D";
public static final String PATIENT = "P";
}

2、初始化聊天回合數(shù)

在聊天之前初始化,這里我們項(xiàng)目的場景是患者發(fā)起咨詢成功后,就在這個(gè)成功后的方法中初始化。

/**
* 發(fā)起咨詢成功
*/
public void consultSuccess() {
// ....其他業(yè)務(wù)邏輯處理

// 初始化聊天回合數(shù)
initChatRoundNum(ConsultDTO consultDTO);
}

/**
* 初始化聊天回合數(shù)
* -- 過期時(shí)間48小時(shí)
* @param consultDTO 咨詢信息
*/
private void initChatRoundNum(ConsultDTO consultDTO) {
// 初始6回合
int chatNum = 6;

// 獲取系統(tǒng)配置的默認(rèn)回合數(shù),這里是偽代碼根據(jù)自己需要編寫。
ParameterDTO parameterDTO = getConfigValue();
if(!ObjectUtils.isEmpty(parameterDTO)) {
chatNum = parameterDTO.getPvalue();
}

// 初始化到redis,key是chat-num:consultId
redisService.set(ChatRoundConstants.CHAT_NUM + consultDTO.getId(),
chatNum, ChatRoundConstants.EXPIRE_TIME);
}

3、更新回合數(shù)

這里是核心邏輯,主要分為兩步:初始化chat-who:consultId,更新chat-num:consultId。

/**
* 發(fā)消息
*/
public void sendMsg() {
// ....其他業(yè)務(wù)邏輯

// 更新聊天回合數(shù)
handleChatRoundNum(consultDTO, consultDetailInfoDTO);
}


/**
* 處理聊天回合數(shù)
* @param consultDTO 咨詢信息
* @param consultDetailInfoDTO 聊天信息
*/
private void handleChatRoundNum(ConsultDTO consultDTO,
ConsultDetailInfoDTO consultDetailInfoDTO) {

// 獲取redis保存的醫(yī)生患者標(biāo)識key
String chatWhoKey = ChatRoundConstants.CHAT_WHO + consultDTO.getId();

// 獲取當(dāng)前發(fā)消息的人對應(yīng)的標(biāo)識
String current = ChatWhoEnum.getCodeById(consultDetailInfoDTO.getSource());

// chat-who:consultId是否存在
if(redisService.exists(chatWhoKey)) {

String chatWhoValue = (String) redisService.get(chatWhoKey);

// 判斷當(dāng)前發(fā)消息的人和chatWho的值是否相同,如果不同,更新chatWho為當(dāng)前發(fā)消息的人。
if(!Objects.equals(ChatWhoEnum.getIdByCode(chatWhoValue),
consultDetailInfoDTO.getSource())) {

// 更新chatWho為當(dāng)前發(fā)消息的人
redisService.setRange(chatWhoKey, current, 0);

// 判斷當(dāng)前發(fā)消息的人是否為D,是D的話才更新回合數(shù)。
if(Objects.equals(ChatWhoEnum.DOCTOR.getId(),
consultDetailInfoDTO.getSource())) {

// 更新chatNum-1
String chatNumKey = ChatRoundConstants.CHAT_NUM + consultDTO.getId();
int chatNumValue = Integer.parseInt(
(String) redisService.get(chatNumKey)
);
if(redisService.exists(chatNumKey) && chatNumValue > 0) {
redisService.decr(chatNumKey);
}

}

}
} else {
// 不存在說明是第一條消息,創(chuàng)建這個(gè)key。
redisService.set(chatWhoKey, current, ChatRoundConstants.EXPIRE_TIME);
}
}

定義的發(fā)消息對象枚舉

/**
* 聊天對象來源的枚舉類
*/
public enum ChatWhoEnum {
// 來源 :
// 0 醫(yī)生
// 1 患者
DOCTOR(0, "D", "醫(yī)生"),
PATIENT(1, "P", "患者");

private final int id;
private final String code;
private final String label;

ChatWhoEnum(final int id, final String code, final String label) {
this.id = id;
this.code = code;
this.label = label;
}

public int getId() {
return id;
}
public String getCode() {
return code;
}
public String getLabel() {
return label;
}

public static String getCodeById(int id) {
for(ChatWhoEnum type: ChatWhoEnum.values()) {
if(type.getId() == id) {
return type.getCode();
}
}
return null;
}

public static Integer getIdByCode(String code) {
for(ChatWhoEnum type: ChatWhoEnum.values()) {
if(code.equalsIgnoreCase(type.getCode())) {
return type.getId();
}
}
return null;
}
}

總結(jié)

其實(shí)寫起來很簡單,思路也不難,但忽然間讓你來實(shí)現(xiàn)這個(gè)小功能的話還是挺費(fèi)勁的,理不清楚就會一直卡在里面,理清楚了瞬間就念頭通達(dá)。

這個(gè)功能目前已經(jīng)上線,并且運(yùn)行穩(wěn)定沒有任何問題,感興趣的可以收藏起來,如果有一天做聊天相關(guān)業(yè)務(wù)的話,說不定就會遇到類似的需求。

責(zé)任編輯:張燕妮 來源: 博客園精華區(qū)
相關(guān)推薦

2010-03-02 16:33:14

linux數(shù)據(jù)備份

2022-02-21 09:10:52

AI模型渲染

2014-05-23 10:37:37

聊天程序PHP聊天程序

2021-05-07 18:12:32

ThreadLocal面試項(xiàng)目

2024-04-24 11:42:21

Redis延遲消息數(shù)據(jù)庫

2020-12-23 10:26:15

中間件ApacheTomca漏洞升級

2022-01-17 11:41:50

前端Vite組件

2023-11-28 14:22:54

Python音頻

2024-05-08 10:20:00

Redis分布式

2020-09-22 10:13:54

開源技術(shù) 趨勢

2022-04-01 18:23:28

HashMapJava 8重構(gòu)

2022-02-12 12:18:59

Delta Chat聊天應(yīng)用開源

2018-01-03 11:05:58

AngularJSPython代碼

2020-12-16 09:53:46

Redis腳本運(yùn)維

2013-05-17 10:37:43

.NETWEB壓力測試WEB壓力測試工具

2014-07-08 09:27:24

SQLSERVER腳本

2021-09-29 15:49:37

Exchange開源用戶開發(fā)者

2020-07-30 09:35:09

Redis分布式鎖數(shù)據(jù)庫

2018-11-16 17:00:05

Python腳本數(shù)據(jù)分析
點(diǎn)贊
收藏

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