> 文档中心 > Redis的string数据结构各场景项目实战

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可以实现的场景就越多啦~~~