redis的高级应用(原子性、expired、mq)

本文探讨了如何利用Redis的原子性实现防超卖、利用TTL处理过期事件,并介绍了如何在高并发场景下使用Redis作为消息队列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        我们在项目中经常会用到nosql来储存访问率高的数据,大多数就是用redis,凭借着比mysql高得多的qps支持数,这样做确实能提高处理速度。那么,redis就只能用来做数据存储查询吗?当然不是!redis还有很多功能等待使用。

       

一、原子性:

        面对高并发抢购的场景,单用mysql记录来判断库存很容易发生超卖的情况。这时候我们可以利用redis decr原子性做锁,实现防止超卖。

1)使用decr方式:

<?php 

		$redis = new Redis();
		$redis->connect('localhost', '6379');
		$key = 'stock';
		
		$data = $redis->decr($key);
		
		if ($data>0){
			header('HTTP/1.1 200 success');
			echo 'success';
		}else{
			header('HTTP/1.1 400 Not Found');
			echo 'false';
		}

2)使用读取重构方式:

<?php 

		$redis = new Redis();
		$redis->connect('localhost', '6379');
		$key = 'stock';//redis数据库key [注:默认redis数据库选择第0号数据库]
		

		$data = $redis->get($key);
		$data = $data - 1;
		$redis->set($key, $data, 600);
		
		if ($data>0){
			header('HTTP/1.1 200 success');
			echo 'success';
		}else{
			header('HTTP/1.1 400 Not Found');
			echo 'false';
		}

我们预先设置stock=200,然后模拟1000并发请求持续性30秒。

1)

2)

从测试结果可以看到,第一种方式执行结果是正确199次,而第二种方式成功814次出现了大量的超卖,如果是在实际的产品中,后果不堪设想。

二、expired过期事件

        redis有ttl属性,当数据超过了livetime自动销毁时会触发事件,我们可以监控这个事件来进行业务处理。比如新订单有三十分钟支付时间,我们就设置订单的ttl为30min,过期事件修改订单为取消状态;又比如,一场线上考试定时两小时,我们就设置ttl为2h,事件触发结束考试。

        具体监控 redis expired过期事件的使用方法可以看一下我的另一篇文章

       https://blog.youkuaiyun.com/u014043168/article/details/109334584

三、消息队列

        无可否认redis队列对比起其他专门的消息队列如rabbitmq、activemq等是弱了点,从可选的部署模式、消息的丢失率都是差一点的,但是胜在小巧。当你需要消息队列,但不想多装的软件,而且消息的必要性又不高,这时候请选择redis的消息队列。

        consummer

<?php

fuction listen(){
        $redis = new Redis();
		$redis->connect(’localhost‘,'6379');
		$redis->auth(123456);
		$key = 'mq_';//redis数据库key [注:默认redis数据库选择第0号数据库]
    		
		while(1) {
			//从队列最前头取出一个值
			$mq_message = $redis->lPop($key);

        //TODO 自定义处理
        var_dump($mq_message);

    }
}

listen();

 producer

<?php

$redis = new Redis();
$redis->connect(’localhost‘,'6379');
$redis->auth(123456);
$key = 'mq_';//redis数据库key [注:默认redis数据库选择第0号数据库]

$redis->rPush($key, 'hello mq');
			
//关闭redis连接
$redis->close();

先cli模式运行consummer,fpm模式运行producer测试推入队列。

### 如何在Java Spring中转换`ResponseEntity<String>` 当处理HTTP请求并返回响应时,经常需要将`ResponseEntity<String>`对象的内容解析或转换成其他形式以便进一步使用。通常情况下,这涉及到从字符串内容反序列化到具体的Java对象。 对于JSON格式的数据,可以利用Jackson库来完成这一过程。下面是一个简单的例子展示如何实现这一点: ```java import org.springframework.http.ResponseEntity; import com.fasterxml.jackson.databind.ObjectMapper; public class ResponseHandler { private final ObjectMapper objectMapper = new ObjectMapper(); public <T> T convertResponseEntity(ResponseEntity<String> response, Class<T> valueType) { try { // 将ResponseEntity中的body部分转化为指定类型的对象 return objectMapper.readValue(response.getBody(), valueType); } catch (Exception e) { throw new RuntimeException("Failed to parse the response entity.", e); } } } ``` 此方法接受两个参数:一个是`ResponseEntity<String>`实例,另一个是指定的目标类类型。通过调用Jackson的`ObjectMapper`工具类的`readValue()`函数,可以从给定的字符串表示中创建一个新的目标类型的实例[^1]。 需要注意的是,在实际应用中应当考虑异常处理机制以及可能存在的网络错误等情况。此外,如果API返回的结果不是标准的JSON结构,则上述代码可能会抛出异常;因此建议开发者根据实际情况调整逻辑以适应不同的场景需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值