关注“Java后端技术全栈”**
回复“面试”获取全套大厂面试材料
缓存的简略意识
在我的项目中存在很多中央应用缓存,缓存是咱们进步零碎的一项必不可少的技术,无论是前端还是后端,都利用到了缓存技术,Mysql
数据库也有应用缓存,所以意识缓存是十分有必要的。
- 前端应用缓存能够升高屡次申请给服务端造成的压力。
- 后端应用缓存,能够升高数据库操作的压力,晋升读取数据的性能。
前端缓存
- 本地缓存
- 网关缓存
服务端缓存
- 过程缓存
- 分布式缓存
其中咱们能够应用Redis
做分布式缓存。
Redis 简略意识
Redis
是一个速度十分快的非关系型数据库(Non-Relational Database),Redis能够存储键值(key-value)数据。其中value能够用5种类型。能够将存储在内存的键值对数据长久化到硬盘上,能够应用复制个性来扩大读性能,还能够做客户端分片来扩大写性能。
为了满足Redis的高性能,它采纳了(in-memory)数据集(Dataset),依据应用场景,能够通过每隔一段时间转存数据集到磁盘,或者追加没挑明了到日志来长久化。也能够禁用长久化,如果你只是须要一个功能丰富、网络传输化的内存缓存。
Redis数据模型
Redis数据模型不仅与关系型数据库不同,也不同于其余简略的NoSQL键值数据存储。
Redis数据类型相似于编程语言的根底类型数据,因而在对于咱们开发人员来说就更易于了解和应用。每个数据类型都反对实用于其类型的操作,受反对的数类型束缚。
场景类型五种:
- String字符串
- Hash哈希
- List列表
- Set汇合
- ZSet有序汇合
Spring Boot集成Redis
减少依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 连接池--><dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId></dependency>
增加配置
properties# Redis数据库索引(默认为0)spring.redis.database=0# Redis服务器地址spring.redis.host=127.0.0.1# Redis服务器连贯端口spring.redis.port=6379# Redis服务器连贯明码(默认为空)spring.redis.password=# 连接池最大连接数(应用负值示意没有限度)spring.redis.jedis.pool.max-active=20# 连接池最大阻塞等待时间(应用负值示意没有限度)spring.redis.jedis.pool.max-wait=-1# 连接池中的最大闲暇连贯spring.redis.jedis.pool.max-idle=10# 连接池中的最小闲暇连贯spring.redis.jedis.pool.min-idle=0# 连贯超时工夫(毫秒)spring.redis.timeout=1000
Redis应用
@RestController()public class RedisController { @Resource private RedisTemplate redisTemplate; /** * 一般存储key-value */ @GetMapping("/setKeyAndValue") public String setKeyAndValue() { redisTemplate.opsForValue().set("name", "java后端技术全栈"); String value = (String) redisTemplate.opsForValue().get("name"); System.out.println("name value =" + value); //设置有效期 redisTemplate.opsForValue().set("name1", "java后端技术栈", 100, TimeUnit.MILLISECONDS); value = redisTemplate.opsForValue().get("name1") == null ? "" : (String) redisTemplate.opsForValue().get("name1"); System.out.println("name1 value =" + value); return "ok"; }}
申请 http://localhost:8080/setKeyAndValue 输入
name value =java后端技术全栈name1 value =java后端技术栈
OK,到此,Redis曾经胜利集成到Spring Boot我的项目中了。
集成进来后,咱们就能够应用Redis来做很多事件了。
1,应用Redis来存储用户登录session
2,应用Redis的setnx和expire来做分布式锁
3,应用Redis的List来做队列
4,应用Redis的ZSet来做排行榜
5,应用自增inrc来确保不会超卖。
…..
上述这些应用场景是有前提条件的,因为没有相对完满的技术,只能是抉择绝对能满足业务场景的就OK。
这里咱们来做一个排行榜的场景。
Redis实现排行榜
需要是做一个用户购买理财产品金额的排行榜,雷同的金额的以购买工夫来排名。
public class UserAccount { private Integer userId; private String userName; private BigDecimal amount; private Date createTime;//get set}
写一个controller演示
@RestController()public class RedisController { @Resource private RedisTemplate redisTemplate; private static final String RANK_KEY_PRE = "user_amount_redis_key"; @GetMapping("/rank") public String rank() { List<UserAccount> userAccountList = new ArrayList<>(); UserAccount userAccount = new UserAccount(); userAccount.setAmount(new BigDecimal("100001")); userAccount.setUserId(10001); userAccount.setUserName("zhangsan"); userAccount.setCreateTime(new Date()); userAccountList.add(userAccount); UserAccount userAccount1 = new UserAccount(); userAccount1.setAmount(new BigDecimal("100000")); userAccount1.setUserId(10002); userAccount1.setUserName("lisi"); userAccount1.setCreateTime(new Date()); userAccountList.add(userAccount1); UserAccount userAccount2 = new UserAccount(); userAccount2.setAmount(new BigDecimal("100000")); userAccount2.setUserId(10003); userAccount2.setUserName("wangwu"); userAccount2.setCreateTime(DateUtil.parseDate("2020-08-15 10:10:10", DateUtil.DATE_TIME_FORMAT)); userAccountList.add(userAccount2); UserAccount userAccount3 = new UserAccount(); userAccount3.setAmount(new BigDecimal("100002")); userAccount3.setUserId(10004); userAccount3.setUserName("laoliu"); userAccount3.setCreateTime(new Date()); userAccountList.add(userAccount3); for (UserAccount ua : userAccountList) { zadd(ua.getUserName(), RANK_KEY_PRE, ua.getAmount().longValue(), ua.getCreateTime().getTime()); } List<ZSetOperations.TypedTuple> tuples = getRankCache(RANK_KEY_PRE, 0, 10); for (int i =0; i <=tuples.size()-1; i++) { ZSetOperations.TypedTuple tuple = tuples.get(i); System.out.println(tuple.getValue() + " 第" +( i )+ "名,分数=" + tuple.getScore()); } return "ok"; } private void zadd(String userName, String key, long points, long updateTime) { double timeRank = points + 1 - updateTime / Math.pow(10, (int) Math.log10(updateTime) + 1); redisTemplate.opsForZSet().add(key, userName, timeRank); }private List<ZSetOperations.TypedTuple> getRankCache(String key, int start, int end) { Set<ZSetOperations.TypedTuple> scoreSet = redisTemplate.opsForZSet().rangeWithScores(key, start, end); if (CollectionUtils.isEmpty(scoreSet)) { return new ArrayList<>(); } List<ZSetOperations.TypedTuple> scoreList = new ArrayList<>(); for (ZSetOperations.TypedTuple item : scoreSet) { scoreList.add(item); } return scoreList; } }
工夫解决工具类
import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class DateUtil { public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; /** * 字符转Date类型 * * @param dateString String 工夫字符串 * @param formatString String 字符串格局;如:yyyy-MM-dd hh:mm:ss,年-月-日 时:分:秒 */ public static Date parseDate(String dateString, String formatString) { if (formatString == null) { formatString = DATE_TIME_FORMAT; } DateFormat dd = new SimpleDateFormat(formatString); try { return dd.parse(dateString); } catch (ParseException e) { throw new RuntimeException(e); } }}
启动我的项目,而后申请
http://localhost:8080/rank
输入
lisi 第4名,分数=100000.84024399419wangwu 第3名,分数=100000.840254259zhangsan 第2名,分数=100001.84024399419laoliu 第1名,分数=100002.84024399419
排名根据进去了。
redis的其余性能前面持续欠缺,本文就搞到这里。
码字不易,期待你们 点在看+分享。
举荐浏览
如何优雅的导出 Excel
终于明确为什么要加 final 关键字了!