redis用途

分佈式鎖(string)

setnx key value,當key不存在時,將 key 的值設爲 value ,返回1。若給定的 key 已經存在,則setnx不作任何動做,返回0。
當setnx返回1時,表示獲取鎖,作完操做之後del key,表示釋放鎖,若是setnx返回0表示獲取鎖失敗。設置過時時期,當遇到宕機時,會在過時後釋放鎖。html

計數器(string)

如知乎每一個問題的被瀏覽器次數
在這裏插入圖片描述java

set key 0
incr key // incr readcount::{帖子id} 每閱讀一次
get key // get readcount::{帖子id} 獲取閱讀量

分佈式全局惟一id(string)

分佈式全局惟一id的實現方式有不少,這裏只介紹用redis實現
在這裏插入圖片描述
每次獲取userId的時候,對userId加1再獲取,能夠改進爲以下形式
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20190110202218333.jpg在這裏插入圖片描述
直接獲取一段userId的最大值,緩存到本地慢慢累加,快到了userId的最大值時,再去獲取一段,一個用戶服務宕機了,也頂多一小段userId沒有用到
incr :自增1
incrby:自增一小段redis

set userId 0
incr usrId //返回1
incrby userId 1000 //返回10001

消息隊列(list)

在list裏面一邊進,一邊出便可sql

# 實現方式一
# 一直往list左邊放
lpush key value 
# key這個list有元素時,直接彈出,沒有元素被阻塞,直到等待超時或發現可彈出元素爲止,上面例子超時時間爲10s
brpop key value 10 
 # 實現方式二
# 一直往list右邊放
rpush key value
blpop key value 10

在這裏插入圖片描述

新浪/Twitter用戶消息列表(list)

在這裏插入圖片描述
假如說小編li關注了2個微博a和b,a發了一條微博(編號爲100)就執行以下命令shell

lpush msg::li 100

b發了一條微博(編號爲200)就執行以下命令:數據庫

lpush msg::li 200

 

假如想拿最近的10條消息就能夠執行以下命令(最新的消息必定在list的最左邊):api

# 下標從0開始,[start,stop]是閉區間,都包含
lrange msg::li 0 9

抽獎活動(set)

# 參加抽獎活動
sadd key {userId} 
 # 獲取全部抽獎用戶,大輪盤轉起來
smembers key 
 # 抽取count名中獎者,並從抽獎活動中移除
spop key count 
 # 抽取count名中獎者,不從抽獎活動中移除
srandmember key count

實現點贊,簽到,like等功能(set)

在這裏插入圖片描述

# 1001用戶給8001帖子點贊
sadd like::8001 1001

# 取消點贊
srem like::8001 1001

# 檢查用戶是否點過贊
sismember like::8001 1001 

# 獲取點讚的用戶列表
smembers like::8001 

# 獲取點贊用戶數
scard like::8001

 

實現關注模型,可能認識的人(set)

在這裏插入圖片描述
seven關注的人
sevenSub -> {qing, mic, james}
青山關注的人
qingSub->{seven,jack,mic,james}
Mic關注的人
MicSub->{seven,james,qing,jack,tom}瀏覽器

# 返回sevenSub和qingSub的交集,即seven和青山的共同關注
sinter sevenSub qingSub -> {mic,james}
 # 我關注的人也關注他,下面例子中我是seven
# qing在micSub中返回1,不然返回0
sismember micSub qing
sismember jamesSub qing
 # 我可能認識的人,下面例子中我是seven
# 求qingSub和sevenSub的差集,並存在sevenMayKnow集合中
sdiffstore sevenMayKnow qingSub sevenSub -> {seven,jack}

 

電商商品篩選(set)

在這裏插入圖片描述
每一個商品入庫的時候即會創建他的靜態標籤列表如,品牌,尺寸,處理器,內存緩存

# 將拯救者y700P-001ThinkPad-T480這兩個元素放到集合brand::lenovo
sadd brand::lenovo 拯救者y700P-001 ThinkPad-T480
sadd screenSize::15.6 拯救者y700P-001 機械革命Z2AIR
sadd processor::i7 拯救者y700P-001 機械革命X8TIPlus

# 獲取品牌爲聯想,屏幕尺寸爲15.6,而且處理器爲i7的電腦品牌(sinter爲獲取集合的交集)
sinter brand::lenovo screenSize::15.6 processor::i7 -> 拯救者y700P-001

排行版(zset)

redis的zset天生是用來作排行榜的、好友列表, 去重, 歷史記錄等業務需求
在這裏插入圖片描述ruby

# user1的用戶分數爲 10
zadd ranking 10 user1
zadd ranking 20 user2
 # 取分數最高的3個用戶
zrevrange ranking 0 2 withscores

 

發佈,訂閱消息(消息通知)

好比你關注了迪麗熱巴,迪麗熱巴發微博你就會收到推送
在這裏插入圖片描述
引用: https://www.cnblogs.com/xinde123/p/8489054.html
redis的發佈與訂閱(發佈/訂閱)是它的一種消息通訊模式,一方發送信息,一方接收信息。
下圖是三個客戶端同時訂閱同一個頻道
在這裏插入圖片描述
下圖是有新信息發送給頻道1時,就會將消息發送給訂閱它的三個客戶端
在這裏插入圖片描述

java實現 redis的發佈訂閱

回顧java如何操做redis:
redis是一種緩存數據庫,它也是C/S的結構,也就是客戶端和服務端,通常來講,在java中,咱們一般使用 jedis(客戶端)去操做redis(服務端),這其中操做的時候,二者之間確定要創建鏈接,就像數據庫連接同樣,在關係型數據庫中,咱們通常都維護一個鏈接池,以達到連接的複用,來省去創建鏈接和關閉鏈接的時間。因此在jedis中,一樣也存在一個jedispool(jedis鏈接池)的概念,咱們都是從池中去取鏈接使用。
引入jedis依賴

<dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.8.0</version>
        </dependency>

創建一個Publisher (發佈者)

package pubsub;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/** * Created by Yuk on 2019/1/10. */
public class Publisher extends Thread{

    private final JedisPool jedisPool;

    public Publisher(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }

    @Override
    public void run() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        Jedis jedis = jedisPool.getResource();   //鏈接池中取出一個鏈接
        while (true) {
            String line = null;
            try {
                line = reader.readLine();
                if (!"quit".equals(line)) {
                    jedis.publish("mychannel", line);   //從 mychannel 的頻道上推送消息
                } else {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

再創建一個訂閱者

package pubsub;

import redis.clients.jedis.JedisPubSub;

/** * Created by Yuk on 2019/1/10. */
public class Subscriber extends JedisPubSub {

    public Subscriber(){}
    @Override
    public void onMessage(String channel, String message) {       //收到消息會調用
        System.out.println(String.format("receive redis published message, channel %s, message %s", channel, message));
    }
    @Override
    public void onSubscribe(String channel, int subscribedChannels) {    //訂閱了頻道會調用
        System.out.println(String.format("subscribe redis channel success, channel %s, subscribedChannels %d",
                channel, subscribedChannels));
    }
    @Override
    public void onUnsubscribe(String channel, int subscribedChannels) {   //取消訂閱 會調用
        System.out.println(String.format("unsubscribe redis channel, channel %s, subscribedChannels %d",
                channel, subscribedChannels));

    }
}

這裏訂閱者須要繼承JedisPubSub,來重寫它的三個方法。用途 註釋上已經寫了,很簡單。

咱們這裏只是定義了一個訂閱者,下面去訂閱頻道

package pubsub;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/** * Created by Yuk on 2019/1/10. */
public class SubThread extends Thread {

    private final JedisPool jedisPool;
    private final Subscriber subscriber = new Subscriber();

    private final String channel = "mychannel";

    public SubThread(JedisPool jedisPool) {
        super("SubThread");
        this.jedisPool = jedisPool;
    }

    @Override
    public void run() {
        System.out.println(String.format("subscribe redis, channel %s, thread will be blocked", channel));
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();   //取出一個鏈接
            jedis.subscribe(subscriber, channel);    //經過subscribe 的api去訂閱,入參是訂閱者和頻道名
        } catch (Exception e) {
            System.out.println(String.format("subsrcibe channel error, %s", e));
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }
}

最後,再寫一個測試類去跑一下。鍵盤輸入消息,訂閱者就會觸發onMessage方法

package pubsub;

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/** * Created by Yuk on 2019/1/10. */
public class PubSubDemo {

    public static void main( String[] args ) {
        // 鏈接redis服務端
        JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379);

        System.out.println(String.format("redis pool is starting, redis ip %s, redis port %d", "127.0.0.1", 6379));

        SubThread subThread = new SubThread(jedisPool);  //訂閱者
        subThread.start();

        Publisher publisher = new Publisher(jedisPool);    //發佈者
        publisher.start();
    }
}

在這裏插入圖片描述

 

原文地址: https://blog.csdn.net/yu_kang/article/details/86254297

相關文章
相關標籤/搜索