Redis数据结构的多种用法
分布式锁(string)
setnx key value,当key不存在时,将 key 的值设为 value ,返回1。若给定的 key 已经存在,则setnx不做任何动作,返回0。
当setnx返回1时,表示获取锁,做完操作以后del key,表示释放锁,如果setnx返回0表示获取锁失败。设置过期时期,当遇到宕机时,会在过期后释放锁。
计数器(string)
如知乎每个问题的被浏览器次数
set key 0
incr key // incr readcount::{帖子id} 每阅读一次
get key // get readcount::{帖子id} 获取阅读量
分布式全局唯一id(string)
分布式全局唯一id的实现方式有很多,这里只介绍用redis实现
每次获取userId的时候,对userId加1再获取,可以改进为如下形式

在list里面一边进,一边出即可
# 实现方式一
# 一直往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)就执行如下命令
lpush msg::li 100
b发了一条微博(编号为200)就执行如下命令:
lpush msg::li 200
假如想拿最近的10条消息就可以执行如下命令(最新的消息一定在list的最左边):
# 下标从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-001和ThinkPad-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天生是用来做排行榜的、好友列表, 去重, 历史记录等业务需求
# 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
Redis数据结构的多种用法的更多相关文章
- Redis 数据结构使用场景
转自http://get.ftqq.com/523.get 一.redis 数据结构使用场景 原来看过 redisbook 这本书,对 redis 的基本功能都已经熟悉了,从上周开始看 redis 的 ...
- Redis 数据结构与内存管理策略(上)
Redis 数据结构与内存管理策略(上) 标签: Redis Redis数据结构 Redis内存管理策略 Redis数据类型 Redis类型映射 Redis 数据类型特点与使用场景 String.Li ...
- Redis数据结构之robj
本文及后续文章,Redis版本均是v3.2.8 我们知道一个database内的这个映射关系是用一个dict来维护的.dict的key固定用一种数据结构来表达,这这数据结构就是动态字符串sds.而va ...
- Redis 数据结构之dict
上篇文章<Redis数据结构概述>中,了解了常用数据结构.我们知道Redis以高效的方式实现了多种数据结构,因此把Redis看做为数据结构服务器也未尝不可.研究Redis的数据结构和正确. ...
- [转]Redis 数据结构简介
Redis 数据结构简介 Redis可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有序集合 ...
- RedisTemplate访问Redis数据结构
https://www.jianshu.com/p/7bf5dc61ca06 Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字 ...
- RedisTemplate访问Redis数据结构(介绍和常用命令)
Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有序集 ...
- 第18章 Redis数据结构常用命令
18-1 字符串的一些基本命令 18-1 :配置Spring关于Redis字符串的运行环境 <bean id="poolConfig" class="redis.c ...
- 5种Redis数据结构详解
本文主要和大家分享 5种Redis数据结构详解,希望文中的案例和代码,能帮助到大家. 转载链接:https://www.php.cn/php-weizijiaocheng-388126.html 2. ...
随机推荐
- Yii实战中8个必备常用的扩展,模块和widget
Yii实战中8个必备常用的扩展,模块和widget 在经过畅K网 的实战后,总结一下在Yii的项目中会经常用到的组件和一些基本的使用方法,分享给大家,同时也给自己留个备忘录,下面我以代码加图片说明. ...
- pycharm使用技巧 + 调试程序-12
Pycharm使用技巧 系出名门:JetBrains 集成开发环境:IDE 功能: Project视图.代码结构视图 代码导航 语法高亮.自动补齐.错误提示.自动修复 代码重构 主流开发框架的支持(D ...
- Intellij IDEA编辑golang时无法加载系统GOPATH变量
问题: 编译go项目时,报找不到包.从日志看,GOPATH与系统设置的不一致. 如何解决:系统的gopath路径,加到Project libraries中 参考:https://segmentfaul ...
- 基于Redis的Spring cache 缓存介绍
目录 Cache API及默认提供的实现 demo 依赖包安装 定义实体类.服务类和相关配置文件 Cache注解 启用Cache注解 @CachePut @CacheEvict @Cacheable ...
- 上下两个div, 一个固定高度, 另一个铺满屏幕
<div class="box"> <div class="el1"></div> <div class=" ...
- IUSER 匿名帐户密码获取
如何获取IUSR帐号和密码呢?有两种方法 1.安装IIS Resources,打开IIS Resources中的Metabase Explorer->机器名->LM->W3SVC-& ...
- fb发布打包外部资源
将资源放在src文件夹下面即可 然后在打包那就会看到资源,勾上即可
- JAVA8-待续
1. 函数式编程,因为在并发和时间驱动编程中的优势,函数式编程又逐渐流行起来 以前是实现一个比较器需要实现Comparator接口,并重写compare方法,以下为两种实现方法(类似还有线程,事件等) ...
- Servlet基本_Filter
1.概念・サーブレットフィルタとは.サーブレットやJSPの「共通の前後処理」を記述するための仕組みです.・フィルタはサーブレットやJSPの前に位置し.実行前と後に.リクエスト.レスポンスに対して任意の ...
- 为什么虚拟DOM更优胜一筹
注意: 虚拟DOM只是实现MVVM的一种方案,或者说是视图更新的一种策略.没有虚拟DOM比MVVM更好一说. 我们回顾传统MVC框架,如backbone,它是将某个模板编译成模板函数,需要更新时,是自 ...