1. 程式人生 > >redis實戰之計數訊號量(未完)

redis實戰之計數訊號量(未完)

計數訊號量是一種鎖,可以讓使用者限制一項資源最多能夠同時被多少個使用者訪問
計數訊號量有如下幾個特徵:
1. 使用前必須要獲取到資源,使用結束後必須要釋放資源
2. 獲取資源失敗後立即將失敗結果返回給使用者

示例:

構建基本的計數訊號量

使用有序集合來構建基本的計數訊號量,使用當前時間戳作為分值,將標識值新增到有序集合裡面,程式在將識別符號新增到有序集合前,清理有序集合中時間戳大於超時數值的識別符號

public String acquireSemaphore(Jedis conn,String semname,int limit,long timeout){
        String identifier=UUID.randomUUID().toString();
        long
now=System.currentTimeMillis(); Pipeline pip=conn.pipelined(); pip.zremrangeByScore(semname, 0, now-timeout*1000); pip.zadd(semname, now, identifier); Response<Long>rank=pip.zrank(semname, identifier); pip.syncAndReturnAll(); if ((long)rank.get()<limit) { return
identifier; } conn.zrem(semname, identifier); System.out.println("remove:"+identifier); return null; }
釋放訊號量
public Long releaseSemaphore(Jedis conn,String semname,String identifier){
        return conn.zrem(semname, identifier);
    }

這個基本的計數訊號量存在一定的問題,在叢集或者分散式系統當中,每臺計算機的時間都有細微的差異。比如說A機器比B機器慢了10毫秒,在A取走最後一個計數訊號量後,B只要在10毫秒內就能取走A所持有的資源

公平訊號量

為了消除時間造成的誤差,我們需要另外兩個資料結構,一個是全域性計數器,另一個是記錄獲得獲得資源的順序sorted set,獲取取得資源排名的時候不再利用時間作為分值排名而是利用全域性計數器的到的值

一定要注意時間單位的換算,否則會導致超時資料漏刪或者多刪的情況

//獲取資源

public String acquireFairSemaphore(Jedis conn,String semname,int limit,long timeout){
        String identifier=UUID.randomUUID().toString();
        //資源擁有者sorted set
        String czset=semname+":owner";
        //全域性計數器
        String ctr=semname+":counter";
        long now=System.currentTimeMillis();
        Transaction trans=conn.multi();
        trans.zremrangeByScore(semname.getBytes(), "0".getBytes(), String.valueOf(now-timeout*1000).getBytes());
        //trans.zremrangeByScore(semname, 0, now-timeout*1000);
        ZParams params=new ZParams();
        params.weights(1,0);
        //czset和semname的交集計算
        trans.zinterstore(czset, params, czset,semname);
        trans.incr(ctr);
        List<Object>results=trans.exec();
        int counter=((Long)results.get(results.size()-1)).intValue();
        trans=conn.multi();
        trans.zadd(semname, now, identifier);
        trans.zadd(czset, counter,identifier);
        trans.zrank(czset, identifier);
        results=trans.exec();
        int result=((Long)results.get(results.size()-1)).intValue();
        if (result<limit) {
            return identifier;
        }
        trans=conn.multi();
        trans.zrem(semname, identifier);
        trans.zrem(czset, identifier);
        trans.exec();
        return null;
    }

//釋放資源
public boolean releaseFairSemaphore(Jedis conn,String semname,String identifier){
        Transaction trans=conn.multi();
        trans.zrem(semname, identifier);
        trans.zrem(semname+":owner", identifier);
        List<Object>results=trans.exec();
        return (long)results.get(results.size()-1)==1;
    }

相關推薦

redis實戰計數訊號()

計數訊號量是一種鎖,可以讓使用者限制一項資源最多能夠同時被多少個使用者訪問 計數訊號量有如下幾個特徵: 1. 使用前必須要獲取到資源,使用結束後必須要釋放資源 2. 獲取資源失敗後立即將失敗結果返回給使用者 示例: 構建基本的計數訊號量 使用

java併發Semaphore(計數訊號

Semaphore一個計數訊號量。從概念上講,訊號量維護了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然後再獲取該許可。每個 release() 新增一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實際的許可物件,Semaphore 只對可用

Java併發程式設計實戰--計數訊號(Semaphore)

計數訊號量(Counting Semaphore)用來控制同時訪問某個特定資源的運算元量,或者同時執行某個指定操作的數量。計數訊號量還可以用來實現某種資源池,或者對容器施加邊界。 Semaphore中管理著一組虛擬的許可(permit),許可的初始數量可通過建

多執行緒 Semaphore 訊號控制

Semaphore(訊號量) 用來控制同時訪問特定資源的執行緒數量。可以起到限流的作用。它與之前寫到的Guava API 中的令牌桶 RateLimiter的區別在於,令牌桶是控制了最終能進入訪問資源的恆定流量。會拋棄掉一些過剩流量的進入。而Semaphore 保證的是進入流量的恆定速率,這些流量最

always on 路實踐(

www vmvare tle ping 集群 vmnet 主機模式 故障 之路 準備:利用vmvare workstation12 克隆了4臺windows server 2008 datacenter,網絡選擇僅主機模式(VMnet8),網關為192.168.214.2

always on 路實踐() 利用VMware克隆 windows 虛擬機器需要注意的事項

準備:利用vmvare workstation12  克隆了4臺windows server 2008 datacenter,網路選擇僅主機模式(VMnet8),閘道器為192.168.214.2 分別是D1 :192.168.214.14 DB1:192.168.214.11 DB2:19

Redis實戰Redis命令

  Redis可以儲存鍵與5種不同資料結構型別之間的對映,這5種資料結構型別分別為string(字串),list(列表),set(集合),hash(雜湊),zset(有序集合),下面將分別對這5種資料型別的控制命令進行總結,熟話說好記性不如爛筆頭,方便以後檢視。 1. 字串命令   Redis種的字串有三

java面試java基礎部分(待續)

1.&與&&區別? &和&&都是邏輯運算子,都是判斷兩邊同時真則為真,否則為假;但是&&當第一個條件不成之後,後面的條件都不執行了,而&

java面試多執行緒(待續)

1.什麼是多執行緒? 在一個應用程式中,同時,有多個不同的執行路徑。 2.執行緒和程序有什麼區別? 執行緒是程序的一條執行路徑,而程序是執行緒的集合。 3.什麼是執行緒同步、非同步? 執行緒同

2018最新JAVA分散式實戰網際網路金融p2p視訊(整版)

課程目錄: 01專案介紹-1 02專案介紹-2 03專案環境搭建-1 04專案環境搭建-2 05專案環境搭建-3 06專案環境搭建-4 07專案環境搭建-5 08分散式環境搭建-1 09分散式環境搭建-2 10分散式環境搭建-3 11驗證碼,redis環境搭建-1 12驗證碼,redis環境搭

Redis實戰Redis + Jedis

用Memcached,對於快取物件大小有要求,單個物件不得大於1MB,且不支援複雜的資料型別,譬如SET 等。基於這些限制,有必要考慮Redis! 相關連結: 言歸正傳,目前Redis大概有3中基於Java語言的Client: JredisJedisRedis4

redis實戰使用redis儲存最近瀏覽的商品資料

注:本文只做教學目的,而在實際的應用場景中,大型的電商網站的訪問量較大,將瀏覽資料儲存於redis中並不可行,望讀者知悉。 關於使用redis儲存最近瀏覽的商品資料,之前沒想到的是,cookie和redis存在本質上的區別。如果使用如本文中所述的方法儲存該資料,所有使用者共

Redis實戰徵服 Redis + Jedis + Spring (二)

不得不說,用雜湊操作來存物件,有點自討苦吃! 不過,既然吃了苦,也做個記錄,也許以後API升級後,能好用些呢?! 或許,是我的理解不對,沒有真正的理解雜湊表。 相關連結: 一、預期 接上一篇,擴充User屬性: Java程式碼   publiccla

Django restful api(待續)

Restful api 符合REST架構設計的API叫做restful api。 那麼什麼是REST呢?REST是所有Web應用都應該遵守的架構設計指導原則。 Representational

windows執行緒間通訊訊號

可以描述一個資源有多少。#include "stdafx.h"#include <windows.h>#include <iostream>#include <process.h>using namespace std;CRITICAL_

Redis實戰Redis 在 Win7 64bit + VS2013 使用

簡介 Redis是一個高效能的key-value資料庫,所支援的value型別包括string(字串)、list(連結串列)、set(集合)、zset(sorted set,有序集合)和hash(雜

Redis實戰徵服 Redis + Jedis + Spring (三)

一開始以為Spring下操作雜湊表,列表,真就是那麼土。恍惚間發現“stringRedisTemplate.opsForList()”的強大,抓緊時間惡補下。 通過spring-data-redis完成LINDEX, LLEN, LPOP, LPUSH, LRANGE, L

C++多執行緒同步Semaphore(訊號)

一、執行緒間同步的幾種方式 從上篇博文中可以發現,當多個執行緒對同一資源進行使用時,會產生“爭奪”的情況,為了避免這種情況的產生,也就出現了執行緒間的同步這個技術。執行緒間的同步有多種方式,在接下來的博文中我會依次介紹幾種主流的同步方式,以及他們之間的區別。在

程序間通訊systemV訊號(semget semop semctl相關操作)

一、什麼是訊號量? 訊號量的本質就是計數器,記錄臨界資源的數目,用來協助程序同步互斥的訪問臨界資源。為什麼不在程序中定義一個全域性變數作為計數器呢?兩個程序間的地址空間是各自獨立的,各自有各自的虛擬記憶體空間。多程序之間不能看到各自程序中的全域性變數。(程序間的虛擬記憶體h

uC/OS-III任務訊號

1.給任務釋出訊號量是一種非常常用的同步方法,因此,在uC/OS-III中,每個任務都有它自己的內嵌訊號量。 2.當建立任務時,任務訊號量會被自動建立,且初始計數為零。 3.等待任務訊號量使用函式OSTaskSemPend(),它的定義位於os_task.c