Redis的string数据结构各场景项目实战
目录
目录
目录
前言
本文示例环境
String类型的使用场景
string-缓存场景:session缓存
0、场景介绍:
1、环境:
2、配置:
3、 java代码:
4、 测试:
string-缓存场景:单值/对象缓存
0、场景介绍
1、环境:
2、配置:
3、java代码:
4、 测试:
string-分布式锁场景:
0、场景介绍
1、环境:
2、配置:
3、java代码:
4、测试:
string-计数器场景:
0、场景介绍
1、环境
2、配置:
3、java代码
总结
前言
Redis常用数据结构:String、List、Hash、Set、Zset。根据数据结构的特点可实现的场景就会多样。所谓这五种数据结构,是key-value存储格式下value中的数据结构为五种。篇幅有限,本文主要对string类型举例~
注:Redis查看命令: help @xx 例如查看操作string类型的命令:help @String 如图
注:zset的查看命令特殊 是 help @sorted_set
本文示例环境
- springboot项目,引入redis。(具体情况具体介绍)
- java使用redisson作为客户端
- 使用到的工具有:nginx,jmeter,ApiPost/PostMan
String类型的使用场景
string-缓存场景:session缓存
0、场景介绍:
拿用户登陆举例:post请求提交了用户名密码,将两者存入session中。即使在分布式环境中,session信息也可以共享。
1、环境:
- 使用spring session与redis的整合,pom引入依赖
org.springframework.boot spring-boot-starter-data-redis 2.1.7.RELEASE org.springframework.session spring-session-data-redis 2.6.1
2、配置:
#指定默认session缓存方式spring: redis: host: xx.xx.130.130 port: 6379 password: 123456 session: store-type: redis
3、 java代码:
@SpringBootApplication@EnableRedisHttpSessionpublic class RedisDemoApplication { public static void main(String[] args) { SpringApplication.run(RedisDemoApplication.class, args); }}
@RestController@RequestMapping("/session")public class SessionController { @PostMapping public String setSession(HttpSession session,String name,String password){ session.setAttribute("name",name); session.setAttribute("password",password); return "ok"; }}
4、 测试:
可以看到用户名密码都被redis缓存
string-缓存场景:单值/对象缓存
0、场景介绍
上个案例中spring session 和redis将用户信息存储,登陆业务中,如果查询有此用户,密码正确,准许登入后,用户的信息经常使用,例如用户的部门信息要拿去做权限等,不妨将用户(这个java对象)缓存在redis中。
1、环境:
- 使用redisson作为客户端,pom引入依赖
- 使用阿里巴巴的fastjson序列化对象为json字符串存入redis
com.alibaba fastjson 1.2.78 org.redisson redisson 3.16.6 org.redisson redisson-spring-boot-starter 3.16.7
2、配置:
和上个例子一样的yml配置文件,没有变。但是要添加一个redisson的配置类
@Configurationpublic class RedissonConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private String port; @Value("${spring.redis.password}") private String password; /** * 配置单节点模式 * * @return redisson实例 */ @Bean public RedissonClient redissonClient() { Config config = new Config(); config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password); return Redisson.create(config); }}
3、java代码:
1)还是上个例子中:多了创建用户对象UserInfo后调用方法缓存用户对象
@RestController@RequestMapping("/session")public class SessionController { @Autowired private CacheService cacheService; @PostMapping public String setSession(HttpSession session, String name, String password){ session.setAttribute("name",name); session.setAttribute("password",password); //---------创建对象 UserInfo userInfo = new UserInfo(name,password); //---------用redis缓存对象 cacheService.cacheUser(userInfo); return "ok"; }}
2)redisson缓存对象
@Servicepublic class CacheService { @Autowired private RedissonClient redissonClient; @Autowired private StringRedisTemplate stringRedisTemplate; public void cacheUser(UserInfo userInfo){ //将java对象转为json 字符串 String userJSONString = JSON.toJSONString(userInfo); //操作redisson 的 API,相当于redis命令:set userInfo ... stringRedisTemplate.opsForValue().set("userInfo", userJSONString); }}
4、 测试:
可以看到redis中缓存了对象(json字符串格式),当然单值缓存就是只存名字啊等。
string-分布式锁场景:
0、场景介绍
传说中的互联网秒杀场景:简例:
- 20个商品库存存在redis中,2台服务器(本地伪分布式,同一服务起个8099端口,再起一个8088端口,使用nginx负载均衡(将请求打到不同机器上))接收200请求(jmeter发送),要保证不多扣不少扣库存。
- 使用redis分布式锁,保证两台机器各自接受的多请求中,同一时刻只有一个请求执行扣减库存,保证数据安全。
1、环境:
- nginx:本次举例使用nginx version: nginx/1.21.0
- jmeter:本次举例使用5.4版本
2、配置:
- redis环境与前述环境一样:
- 提前向redis存库存数量20个:即set stock 20
- nginx配置(只展示重点部分:upstream + location里):
http { #服务器集群,并起个名字redisdemo upstream redisdemo { server 127.0.0.1:8099; server 127.0.0.1:8088;} #gzip on; server { listen8080; server_name localhost; location / { #这里的名字和上面配置的对上redisdemoproxy_pass http://redisdemo;proxy_redirect default; } }}
- 项目用两个端口分别启动
- jmeter配置:
- 200个线程,3秒跑完,循环一次(图一)
- 配置请求地址(nginx代理地址localhost:8080)+接口名(/deduct_stock)(图二)
到此,准备工作已做好。
3、java代码:
扣减库存的接口代码:
@RestControllerpublic class RedisLockController { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private RedissonClient redissonClient; @RequestMapping("/deduct_stock") public String deductStock(){ //给锁起个名字 String lockKey = "product_stock"; //获取锁对象 RLock redissonLock = redissonClient.getLock(lockKey); try { redissonLock.lock(); //获取库存 int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock")); //库存充足 if (stock > 0) { //扣减库存 int realStock = stock - 1; //实际库存存入redis stringRedisTemplate.opsForValue().set("stock", realStock + ""); System.out.println("扣减成功,剩余库存:" + realStock); } else { System.out.println("扣减失败,库存不足"); } } finally { //释放锁 redissonLock.unlock(); } return "ok"; }}
4、测试:
1)jmeter的聚合报告
2)控制台查看
redis分布式锁保证了数据安全:不会超卖。
string-计数器场景:
0、场景介绍
比如某个直播间/文章,有多少人进入/查看,可以用redis实现计数器的功能:
1、环境
- 与前面环境一致没有变动
- jmeter新建任务3s200请求模拟访问阅读大v博主的文章
2、配置:
- 与上述配置不变:仍使用nginx代理两台服务器
3、java代码
@RestControllerpublic class CounterController { @Autowired private StringRedisTemplate stringRedisTemplate; @RequestMapping("/counter") public String counter(){ //谁的文章 String userName = "大V博主"; //哪篇文章 String articleName = "论xxxxxx"; Long increment = stringRedisTemplate.opsForValue().increment(userName+":"+articleName+":"+"how-many"); return "ok"; }}
4、测试:
总结
先写到这里呀~欢迎补充,想到其它案例再来补充! 其实无非就是API的操作,场景很多样,对redis的存储数据结构和命令了解更多,用redis可以实现的场景就越多啦~~~