国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

Redis到底該如何利用(三)?

2019-11-17 02:45:04
字體:
供稿:網(wǎng)友

Redis到底該如何利用(三)?

上兩篇受益匪淺,秉著趁熱打鐵,不挖到最深不罷休的精神,我決定追加這篇。上一篇里最后我有提到實現(xiàn)分級緩存管理應(yīng)該是個可行的方案,因此今天特別實踐了一下。不過緩存分級之后也發(fā)現(xiàn)了一些問題,例如下圖:

當(dāng)appServerA修改了數(shù)據(jù),并同步到Redis/DB之后,如何讓appServerB也能更新本地緩存呢?雖然Redis的出現(xiàn)是為了解決這個問題的,但是分級方案里,MemoryCache還是需要保留。那么如何保存呢?我嘗試了下面的幾種方式,現(xiàn)在我們逐一來看。

全數(shù)據(jù)增量同步

所謂全數(shù)據(jù)校驗,即所有的緩存數(shù)據(jù)首先都同步至Redis,然后根據(jù)數(shù)據(jù)的時間戳來進(jìn)行同步。分解步驟如下:

  1. 首先將緩存的數(shù)據(jù)初始化,同步至Redis和MemoryCache,保持初始數(shù)據(jù)的同步
  2. 第二步,每當(dāng)操作了數(shù)據(jù)之后,給記錄一個時間戳標(biāo)識最近的更新。
  3. MemoryCache定時或者每次取數(shù)據(jù)的時候,以最近的一個同步的時間戳開始同步到現(xiàn)在的時間戳

上面的方案咱們落地到.NET+Redis又該怎么處理呢?

第一步很簡單直接跳過,第二步就有點問題了,這個時間戳要便于redis的排序和獲取,考慮到這些問題,我覺得取linux的數(shù)字型時間戳比較靠譜,再配合SortSet來建立索引,進(jìn)行同步,看起來的確不錯。那么來看下代碼:

本篇還是以User為例,可能場景不適合,大家將就理解

public void UpdateToRedis(User user){            var redis = ConnectionMult

同步:

public void Sync(double timespan){            var redis = ConnectionMultiplexer.Connect("localhost");            var db = redis.GetDatabase();            TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0);            double time = Convert.ToInt64(ts.TotalSeconds);//計算Unix時間戳                        //同步時間范圍內(nèi)的記錄,這里增加時間范圍,以防止一些數(shù)據(jù)不準(zhǔn)確的問題            var members = db.SortedSetRangeByScore("capqueen:user:index", timespan, time);            var keys = members.ToList().Select<RedisValue, RedisKey>(i => i.ToString());            var values = db.StringGet(keys.ToArray());            //構(gòu)造List Json以加速解析            var portsJson = new StringBuilder("[");            values.ToList().ForEach(item =>            {                if (!string.IsNullOrWhiteSpace(item))                {                    portsJson.Append(item).Append(",");                }            });            portsJson.Append("]");            var users = JsonConvert.DeserializeObject<List<User>>(portsJson.ToString());            //和內(nèi)存的List<User>做同步            ...            //END}

上面的代碼只是實例,實際運行的時候感覺還不是特別靠譜。

消息通知

增量同步是好,但是同時時機也是個問題,時機不對,就會影響用戶體驗。而且感覺我們還是無法很好的掌控數(shù)據(jù)。那么有沒有一種方式可以及時的通知到appServer更新緩存呢?這里我腦子里冒出來的是.NET Event機制。

我覺得.NET因為有了優(yōu)秀的Event機制,才讓我覺得它使用起來很方便

但是這里是服務(wù)器之間的通信,我想非Scoket莫屬了,之間做過Scoket雙向通信,印象特別深刻,這樣的場景讓我自然而然的想到了這個方案??墒翘貏e的增加一個socket,本身復(fù)雜的架構(gòu)要更復(fù)雜了,還是尋求一個靠譜的中間件比較適合??催^Redis的功能列表的同學(xué),一定沒忘記Redis還有一個訂閱發(fā)布,pub/sub功能。于是我就利用了這個功能,設(shè)計了如下的方案:

  1. 為app增加一個sub線程,用于接收redis訂閱消息
  2. 在每一個緩存對象更新的同時,增加異步pub消息到redis

先來看下Redis的,pub/sub功能,請看文檔

redis提供指定channel的訂閱發(fā)布功能,每一個Client可以訂閱指定的channel消息,也可以向指定的channel發(fā)送消息。

利用ServiceStack.Redis的pub/sub功能實現(xiàn)如下:

using (var redisConsumer = new RedisClient(TestConfig.SingleHost))using (var subscription = redisConsumer.CreateSubscription()){    subscription.OnSubscribe = channel =>    {        //訂閱事件    };    subscription.OnUnSubscribe = channel =>    {       //退訂事件    };    subscription.OnMessage = (channel, msg) =>    {        // 這里的msg,我為了測試定義成了userid        var user= redisConsumer.As<User>().GetById(msg);//從Redis獲取記錄        UpdateLocalCache(user);//更新本地    };      subscription.SubscribeToChannels("capqueen:redis:events"); //blocking}

發(fā)送:

using (var redisPublisher = new RedisClient("localhost")){    redisPublisher.PublishMessage("capqueen:redis:events", userId);//發(fā)送消息}

這里我覺得message應(yīng)該定義成一個消息體,接收處理應(yīng)該根據(jù)具體的消息定義來具體處理,因為訂閱發(fā)布的通道顯然應(yīng)該是合理利用,如果一個業(yè)務(wù)一個通道,有點太多了。

當(dāng)然這個實現(xiàn)起來又要講一大篇了,這里不多說明。

總結(jié)

本篇文章,根據(jù)上一篇提的方案做了一些實現(xiàn),不足之處太多了。例如事件丟了怎么辦?如何正確的處理消息缺失,記錄少了之類的特殊情況應(yīng)該是很重要的。我暫時還沒想到方案,不知道前輩們?nèi)绾慰创@樣的問題。可能我還是濫用了Redis,為了技術(shù)而技術(shù)了,不過不嘗試碰下壁,怎么能得到成長。所謂兼聽則明 偏信則暗,我感覺自己有點不見棺材不落淚了。請前輩們不吝指教!


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 杭州市| 利川市| 南宁市| 嘉荫县| 恩平市| 中江县| 漳平市| 洛扎县| 桦南县| 谷城县| 清流县| 炉霍县| 吴川市| 濮阳市| 同心县| 耿马| 盐津县| 玉门市| 盐边县| 安庆市| 临泉县| 陕西省| 临沭县| 通辽市| 云和县| 新源县| 永德县| 晋州市| 福建省| 新安县| 乌兰察布市| 淳化县| 博白县| 辽中县| 徐闻县| 金坛市| 邹城市| 元江| 望城县| 卓尼县| 阳高县|