redis用途

妖狐艹你老母 2021-12-03 19:45 450阅读 0赞

分布式锁(string)

setnx key value,当key不存在时,将 key 的值设为 value ,返回1。若给定的 key 已经存在,则setnx不做任何动作,返回0。
当setnx返回1时,表示获取锁,做完操作以后del key,表示释放锁,如果setnx返回0表示获取锁失败。设置过期时期,当遇到宕机时,会在过期后释放锁。

计数器(string)

如知乎每个问题的被浏览器次数
在这里插入图片描述

  1. set key 0
  2. incr key // incr readcount::{帖子id} 每阅读一次
  3. 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:自增一小段

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

消息队列(list)

在list里面一边进,一边出即可

  1. # 实现方式一
  2. # 一直往list左边放
  3. lpush key value
  4. # key这个list有元素时,直接弹出,没有元素被阻塞,直到等待超时或发现可弹出元素为止,上面例子超时时间为10s
  5. brpop key value 10
  6. # 实现方式二
  7. # 一直往list右边放
  8. rpush key value
  9. blpop key value 10

在这里插入图片描述

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

在这里插入图片描述
假如说小编li关注了2个微博a和b,a发了一条微博(编号为100)就执行如下命令

  1. lpush msg::li 100

b发了一条微博(编号为200)就执行如下命令:

  1. lpush msg::li 200

假如想拿最近的10条消息就可以执行如下命令(最新的消息一定在list的最左边):

  1. # 下标从0开始,[start,stop]是闭区间,都包含
  2. lrange msg::li 0 9

抽奖活动(set)

  1. # 参加抽奖活动
  2. sadd key {userId}
  3. # 获取所有抽奖用户,大轮盘转起来
  4. smembers key
  5. # 抽取count名中奖者,并从抽奖活动中移除
  6. spop key count
  7. # 抽取count名中奖者,不从抽奖活动中移除
  8. srandmember key count

实现点赞,签到,like等功能(set)

在这里插入图片描述

  1. # 1001用户给8001帖子点赞
  2. sadd like::8001 1001
  3. # 取消点赞
  4. srem like::8001 1001
  5. # 检查用户是否点过赞
  6. sismember like::8001 1001
  7. # 获取点赞的用户列表
  8. smembers like::8001
  9. # 获取点赞用户数
  10. scard like::8001

实现关注模型,可能认识的人(set)

在这里插入图片描述
seven关注的人
sevenSub -> {qing, mic, james}
青山关注的人
qingSub->{seven,jack,mic,james}
Mic关注的人
MicSub->{seven,james,qing,jack,tom}

  1. # 返回sevenSub和qingSub的交集,即seven和青山的共同关注
  2. sinter sevenSub qingSub -> {mic,james}
  3. # 我关注的人也关注他,下面例子中我是seven
  4. # qing在micSub中返回1,否则返回0
  5. sismember micSub qing
  6. sismember jamesSub qing
  7. # 我可能认识的人,下面例子中我是seven
  8. # 求qingSub和sevenSub的差集,并存在sevenMayKnow集合中
  9. sdiffstore sevenMayKnow qingSub sevenSub -> {seven,jack}

电商商品筛选(set)

在这里插入图片描述
每个商品入库的时候即会建立他的静态标签列表如,品牌,尺寸,处理器,内存

  1. # 将拯救者y700P-001和ThinkPad-T480这两个元素放到集合brand::lenovo
  2. sadd brand::lenovo 拯救者y700P-001 ThinkPad-T480
  3. sadd screenSize::15.6 拯救者y700P-001 机械革命Z2AIR
  4. sadd processor::i7 拯救者y700P-001 机械革命X8TIPlus
  5. # 获取品牌为联想,屏幕尺寸为15.6,并且处理器为i7的电脑品牌(sinter为获取集合的交集)
  6. sinter brand::lenovo screenSize::15.6 processor::i7 -> 拯救者y700P-001

排行版(zset)

redis的zset天生是用来做排行榜的、好友列表, 去重, 历史记录等业务需求
在这里插入图片描述

  1. # user1的用户分数为 10
  2. zadd ranking 10 user1
  3. zadd ranking 20 user2
  4. # 取分数最高的3个用户
  5. 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依赖

  1. <dependency>
  2. <groupId>redis.clients</groupId>
  3. <artifactId>jedis</artifactId>
  4. <version>2.8.0</version>
  5. </dependency>

建立一个Publisher (发布者)

  1. package pubsub;
  2. import redis.clients.jedis.Jedis;
  3. import redis.clients.jedis.JedisPool;
  4. import java.io.BufferedReader;
  5. import java.io.IOException;
  6. import java.io.InputStreamReader;
  7. /** * Created by Yuk on 2019/1/10. */
  8. public class Publisher extends Thread{
  9. private final JedisPool jedisPool;
  10. public Publisher(JedisPool jedisPool) {
  11. this.jedisPool = jedisPool;
  12. }
  13. @Override
  14. public void run() {
  15. BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
  16. Jedis jedis = jedisPool.getResource(); //连接池中取出一个连接
  17. while (true) {
  18. String line = null;
  19. try {
  20. line = reader.readLine();
  21. if (!"quit".equals(line)) {
  22. jedis.publish("mychannel", line); //从 mychannel 的频道上推送消息
  23. } else {
  24. break;
  25. }
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }
  31. }

再建立一个订阅者

  1. package pubsub;
  2. import redis.clients.jedis.JedisPubSub;
  3. /** * Created by Yuk on 2019/1/10. */
  4. public class Subscriber extends JedisPubSub {
  5. public Subscriber(){}
  6. @Override
  7. public void onMessage(String channel, String message) { //收到消息会调用
  8. System.out.println(String.format("receive redis published message, channel %s, message %s", channel, message));
  9. }
  10. @Override
  11. public void onSubscribe(String channel, int subscribedChannels) { //订阅了频道会调用
  12. System.out.println(String.format("subscribe redis channel success, channel %s, subscribedChannels %d",
  13. channel, subscribedChannels));
  14. }
  15. @Override
  16. public void onUnsubscribe(String channel, int subscribedChannels) { //取消订阅 会调用
  17. System.out.println(String.format("unsubscribe redis channel, channel %s, subscribedChannels %d",
  18. channel, subscribedChannels));
  19. }
  20. }

这里订阅者需要继承JedisPubSub,来重写它的三个方法。用途 注释上已经写了,很简单。

我们这里只是定义了一个订阅者,下面去订阅频道

  1. package pubsub;
  2. import redis.clients.jedis.Jedis;
  3. import redis.clients.jedis.JedisPool;
  4. /** * Created by Yuk on 2019/1/10. */
  5. public class SubThread extends Thread {
  6. private final JedisPool jedisPool;
  7. private final Subscriber subscriber = new Subscriber();
  8. private final String channel = "mychannel";
  9. public SubThread(JedisPool jedisPool) {
  10. super("SubThread");
  11. this.jedisPool = jedisPool;
  12. }
  13. @Override
  14. public void run() {
  15. System.out.println(String.format("subscribe redis, channel %s, thread will be blocked", channel));
  16. Jedis jedis = null;
  17. try {
  18. jedis = jedisPool.getResource(); //取出一个连接
  19. jedis.subscribe(subscriber, channel); //通过subscribe 的api去订阅,入参是订阅者和频道名
  20. } catch (Exception e) {
  21. System.out.println(String.format("subsrcibe channel error, %s", e));
  22. } finally {
  23. if (jedis != null) {
  24. jedis.close();
  25. }
  26. }
  27. }
  28. }

最后,再写一个测试类去跑一下。键盘输入消息,订阅者就会触发onMessage方法

  1. package pubsub;
  2. import redis.clients.jedis.JedisPool;
  3. import redis.clients.jedis.JedisPoolConfig;
  4. /** * Created by Yuk on 2019/1/10. */
  5. public class PubSubDemo {
  6. public static void main( String[] args ) {
  7. // 连接redis服务端
  8. JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379);
  9. System.out.println(String.format("redis pool is starting, redis ip %s, redis port %d", "127.0.0.1", 6379));
  10. SubThread subThread = new SubThread(jedisPool); //订阅者
  11. subThread.start();
  12. Publisher publisher = new Publisher(jedisPool); //发布者
  13. publisher.start();
  14. }
  15. }

在这里插入图片描述

原文地址: https://blog.csdn.net/yu\_kang/article/details/86254297

转载于:https://www.cnblogs.com/sunpengblog/p/11161829.html

发表评论

表情:
评论列表 (有 0 条评论,450人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Redis-Redisson介绍和用途

    什么是分布式锁?实现分布式锁的常用三种方式 在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。那具体什么是分布式锁,分布式

    相关 Matlab 用途

    Matlab优点: 1.高效的数值计算功能。目前其他编程语言以及其他类似的数学软件无可替代; 2.完备的计算结果和编程可视化功能。这一点其他软件,无可替代; 3.接近

    相关 ZooKeeper用途

    ZooKeeper还可以用作其他用途,例如: 数据发布与订阅(配置中心) 负载均衡 命名服务(Naming Service) 分布式通知/协调

    相关 Nginx用途

    一、HTTP静态服务器:          存储图片,文件等静态资源。 二、负载均衡: 当一台web服务器不够用时,需要添置一台web服务器,这时候

    相关 redis用途

    分布式锁(string) setnx key value,当key不存在时,将 key 的值设为 value ,返回1。若给定的 key 已经存在,则setnx不做任何动