文档章节

SB集成Redis学习笔记之实际应用场景-java干货

z77z
 z77z
发布于 2017/02/06 21:17
字数 1818
阅读 518
收藏 45

个人博客:http://z77z.oschina.io/

此项目下载地址:https://git.oschina.net/z77z/springboot_mybatisplus

Redis的特性

  • Strings:Strings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字. 常用命令: set,get,decr,incr,mget 等。 常用方法:
  1. 获取字符串长度
  2. 往字符串append内容
  3. 设置和获取字符串的某一段内容
  4. 设置及获取字符串的某一位(bit)
  5. 批量设置一系列字符串的内容
  • Hashs:Redis Hash对应Value内部实际就是一个HashMap,常用命令:hget,hset,hgetall 等。

  • Lists:Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。 常用命令:lpush,rpush,lpop,rpop,lrange等。

  • Sets:Sets 集合的概念就是一堆不重复值的组合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能。 常用命令:sadd,spop,smembers,sunion 等。

  • Sorted Sets:Redis sorted set的使用场景与set类似,区别是set不是自动有序的。sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。 常用命令:zadd,zrange,zrem,zcard等

下面就根据这几个特性,也就是Redis支持的数据类型,来完成以下场景的实现。

场景一:简单计数功能

Redis是一个很好的计数器,计数器是 Redis 的原子性自增操作可实现的最直观的模式了,它的想法相当简单:每当某个操作发生时,向 Redis 发送一个 INCR 命令。使用场景比如网站的访问数,注册用户数,文章的点赞数,高并发的秒杀活动,分布式序列号生成等等统计计数的功能实现。Redis 解决这类计数问题得心应手,相比关系数据库速度更快,消耗资源更少。还可以通过set()方法来重置计数。

// 简单计数
	@Test
	public void test1() {
		try {
			ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
			//计数前打印
			System.out.println(opsForValue.get("test1"));
			for (int i = 0; i < 100; i++) {
				//计数,第一个参数为key值,第二个参数为每次增加计数的单位
				opsForValue.increment("test1", 1);
			}
			//计数后打印
			System.out.println(opsForValue.get("test1"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

场景二:按时间统计计数

有时候除了简单的计数外,比如注册用户数需要按日统计,处理方法比较简单,把日期带入计数器 key 就可以。以此类推,还可以按其他方式进行统计计数,只需要把统计的方式添加到key值就可以了

// 按时间计数 
	@Test
	public void test2() {
		//将日期添加到key值中
		String key = "test2_" + new SimpleDateFormat("yyyy-MM-dd").format(new Date());
		try {
			ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
			System.out.println(opsForValue.get(key));
			for (int i = 0; i < 100; i++) {
				opsForValue.increment(key, 1);
			}
			System.out.println(opsForValue.get(key));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

场景三:按模糊Key值查询

在按条件统计计数的时候,把时间加入到了key值中,有时候要只是查询某个对象的统计数时,就可以使用模糊Key值查询。

// 模糊K值查询
	@Test
	public void test3() {
		try {
			ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
			//先获取前缀为test的Key值列表。
			Set<String> keys = stringRedisTemplate.keys("test*");
			//遍历满足条件的Key值获取对应的value值
			for (String a : keys) {
				System.out.println(a + ":" + opsForValue.get(a));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

场景四:设置Key的有效时间(防止高并发访问)

在redis中可以设置key值的有效时间,用户访问链接的时候,将用户的唯一信息比如ip地址等为key值,时间为value值,在redis中记录一下,在用户再次访问的时候,通过key值获取前一次访问的时间,比较时间的间隔,如果低于阀值,就拒绝这次请求,防止用户多次访问。这里只是写下在spring的RedisTemplate接口怎么使用。具体的逻辑实现自己搞定。

// 设置key值的有效时间
	@Test
	public void test4() {
		try {
			ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
			opsForValue.set("test4", "test4");
			System.out.println(opsForValue.get("test4"));
			// TimeUnit.SECONDS:解释定时参数的单位
			// MICROSECONDS 微秒 一百万分之一秒(就是毫秒/1000)
			// MILLISECONDS 毫秒 千分之一秒
			// NANOSECONDS 毫微秒 十亿分之一秒(就是微秒/1000)
			// SECONDS 秒
			// MINUTES 分钟
			// HOURS 小时
			// DAYS 天
			if(stringRedisTemplate.expire("test4", 5, TimeUnit.SECONDS)){
				System.out.println("设置过期时间成功,等待。。。。");
				Thread.sleep(5001);
			}
			System.out.println(opsForValue.get("test4"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

场景五:使用hashs存储获取修改java对象

在实际开发中,我们经常将一些结构化的信息打包成HashMap,在客户端序列化后存储为一个字符串的值,比如用户的昵称、年龄、性别、积分等,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。

而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。因为Redis的Hash结构是以对象的名字作为redis的key值,以对象的唯一属性值作为hash的key值,以对象来作为redis的value值。结构图如下:

hashs存储结构图

// 使用hashs存储获取对象
	@Test
	public void test5(){
		BeautifulPictures beautifulPictures = beautifulPicturesService.selectById(1);
		HashOperations<String, Object, BeautifulPictures> hash = redisTemplate.opsForHash();
		hash.put("test5",beautifulPictures.getId(),beautifulPictures);
		System.out.println(hash.get("test5", beautifulPictures.getId()));
	}

场景六:使用lists有序存储读取

适用于获取最近N个操作的数据。

//使用lists存储读取 有序
	@Test
	public void test6(){
		ListOperations<String, String> list = stringRedisTemplate.opsForList();
		list.leftPush("test6", "1");
		list.leftPush("test6", "2");
		list.leftPush("test6", "3");
		list.leftPush("test6", "4");
		list.leftPush("test6", "5");
		list.leftPush("test6", "6");
		list.leftPush("test6", "7");
		//保持链表只有3位
		list.trim("test6", 0, 2);
		System.out.println(list.range("test6", 0, list.size("test6")-1));
	}

场景七:使用sets存储读取 无序 去重 求差集,交集,并集

//使用set存储读取  无序 去重  求差集,交集,并集
	@Test
	public void test7(){
		SetOperations<String, String> set = stringRedisTemplate.opsForSet();
		set.add("test7_1", "2", "1","2","3","4","4","3");
		set.add("test7_2", "2", "6","2","3","7","6","5");
		System.out.println("全部成员"+set.members("test7_1"));
		System.out.println("差集"+set.difference("test7_1", "test7_2"));
		System.out.println("交集"+set.intersect("test7_1", "test7_2"));
		System.out.println("并集"+set.union("test7_1", "test7_2"));
	}

场景八:Sorted Set 存取数据 排序

//Sorted Set 存取数据 排序  相比sets 保存时多一个权重参数score,相当于按照此参数来排序
	@Test
	public void test8(){
		ZSetOperations<String, String> zSet = stringRedisTemplate.opsForZSet();
		zSet.add("test8", "use1", 9);
		zSet.add("test8", "use2", 1);
		zSet.add("test8", "use3", 5);
		zSet.add("test8", "use4", 9);
		//对应的score值增加
		//zSet.incrementScore("test8", "use1", 1);
		System.out.println(zSet.reverseRange("test8", 0, zSet.size("test8")-1));
	}

© 著作权归作者所有

z77z

z77z

粉丝 129
博文 17
码字总数 32226
作品 0
成都
程序员
私信 提问
Spring Boot学习笔记

多模块开发 [SpringBoot学习]-IDEA创建Gradle多Module结构的SpringBoot项目 RabbitMQ RabbitMQ 安装 linux安装RabbitMQ详细教程 Ubuntu 16.04 RabbitMq 安装与运行(安装篇) ubantu安装...

OSC_fly
2018/07/26
0
0
美团猫眼团队面试题:Maven+OSGi+Spring+Zookeeper+Dubb

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/t4i2b10X4c22nF6A/article/details/84327220 交叉一面 concurrent包下面用过哪些? countdownlatch功能实现 ...

JAVA高级架构v
2018/11/21
0
0
拼多多Java后端团队面试题:epoll+集群+事务隔离+Kafka+分布式等

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/t4i2b10X4c22nF6A/article/details/86133163 一面 自我介绍 介绍一下mysql索引?为什么用B+树? 网络IO模型?...

JAVA高级架构v
01/09
0
0
京东4面(Java研发):事务隔离+乐观锁+HashMap+秒杀设计+微服务

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/t4i2b10X4c22nF6A/article/details/84347063 一面(基础面:约五十分钟) 自我介绍,主要讲讲做了什么和擅长什...

JAVA高级架构v
2018/11/22
0
0
实际项目中是选用Map还是选用Redis作为缓存?为什么?

参考网页 https://segmentfault.com/q/1010000009106416 实际项目中是选用Map还是选用Redis作为缓存?为什么? 具体选择Map还是Redis作为缓存,要看具体的需求,具体的应用场景 本地缓存和分...

karma123
2018/06/27
135
5

没有更多内容

加载失败,请刷新页面

加载更多

黑客之道-40本书籍助你快速入门黑客技术免费下载

场景 黑客是一个中文词语,皆源自英文hacker,随着灰鸽子的出现,灰鸽子成为了很多假借黑客名义控制他人电脑的黑客技术,于是出现了“骇客”与"黑客"分家。2012年电影频道节目中心出品的电影...

badaoliumang
昨天
9
0
很遗憾,没有一篇文章能讲清楚线程的生命周期!

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。 ...

彤哥读源码
昨天
11
0
jquery--DOM操作基础

本文转载于:专业的前端网站➭jquery--DOM操作基础 元素的访问 元素属性操作 获取:attr(name);$("#my").attr("src"); 设置:attr(name,value);$("#myImg").attr("src","images/1.jpg"); ......

前端老手
昨天
5
0
Django的ChoiceField和MultipleChoiceField错误提示,选择一个有效的选项

在表单验证时提示错误:选择一个有效的选项 例如有这样一个表单: class ProductForm(Form): category = fields.MultipleChoiceField( widget=widgets.SelectMultiple(), ...

编程老陆
昨天
10
0
Vue核心概念及特性 (一)

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。 > 特点: 易用,灵活,高效,渐进式框架。 > 可以随意组合需要用到的模块 vue + components + vue-router + vuex + v...

前端优选
昨天
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部