我这操作很可以!异步结果通知实现—基于Redis实现

Redis异步实现解析 当使用同步连接时,客户端发送一个命令给 Redis 服务器,并在收到服务器响应之后才能继续执行后续的操作。在同步连接中,客户端在执行命令时会阻塞当前线程,等待服务器的响应,直到响应返回或超时。允许客户端在发送命令后不等待响应,可以继续执行其他操作,适用于高性能和高并发场景。以下示例展示了如何实现 Redis 异步连接,包括 Reactor 的实现、Redis 适配器以及主体代码。实现异步连接需要一个 Redis 驱动,该驱动需要将 Redis 连接融入项目中的。 阅读详情

迪迦早期精彩文章(希望对大家有所帮助,直接点击即可阅读):

华为大神珍藏版:SpringBoot全优笔记,面面俱到太全了

涨薪60%!从小厂逆袭,坐上美团L8技术专家(附面经+心得)

专科出身,2年进入苏宁,5年跳槽阿里,论我是怎么做到的?

就离谱?最新Java架构师全路线总结+高频面试题,这也太强了吧!

阿里大佬倾情力荐:Java全线成长宝典,从P5到P8一应俱全!

前段时间,我在内存中实现了一个简单异步通知框架。但由于没有持久化功能,应用重启就会导致数据丢失,且不支持分布式和集群。今天这篇笔记,引入了 Redis 来解决这些问题,以下是几点理由:

  • 数据结构丰富,支持 List、Sorted Set 等
  • 具有持久化功能,消息的可靠性能得到保证
  • 高可用性,支持单机、主从、集群部署
  • 项目中已使用,接入成本更低

基于 Redis 实现延时队列也有几种方法,展开详细讲讲。

基于键事件通知实现

Redis 2.8.0 版本以后就具有了 键事件通知(注,还有个键空间通知,注意区别),基于 Pub/Sub 发布订阅实现,详见 官网。而我们正好可以利用这个特性,实现异步通知的延迟功能,数据流转如下:

异步结果通知实现——基于Redis实现,我这操作很可以

大概逻辑:当首次通知、或通知失败时,设置(重新设置)在 Redis 对应的 Key 的过期时间,Redis 会监听过期事件,发生事件时通知订阅者,订阅者接收到事件,做逻辑处理。下面看具体的实现。

首先,修改 Redis 端配置打开功能。由于该功能会消耗一些 CPU 性能,所以在配置文件中是 默认关闭 的。Ex表示打开 键过期事件通知,每当有过期键被删除时发送,订阅者能收到 接收到被执行事件的键的名字

notify-keyspace-events Ex

其次,想要在 SpringBoot 中,订阅到 Redis 的事件,也需要两个步骤:
1、继承
org.springframework.data.redis.listener.adapter.MessageListenerAdapter 类,创建自己的监听器

@Component
public class OrderExpireEventListener extends MessageListenerAdapter {
    @Override
    public void onMessage(Message message, byte[] pattern) {
          byte[] body = message.getBody();
          String msg = redisWrapper.getRedisTemplate().getStringSerializer().deserialize(body);
          // do something...
          
          // 假如通知失败,需要重新计算下次通知时间,设置 Redis
          // 至于数据类型,String 即可
    }
}

2、将创建的监听器,注册(委托设计模式)给
RedisMessageListenerContainer

@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory factory, 
OrderExpireEventListener adapter) {
    RedisMessageListenerContainer container = new RedisMessageListenerContainer();
    container.setConnectionFactory(factory);
    container.addMessageListener(adapter, new PatternTopic("__keyevent@0__:expired"));
    return container;
}

这里有个点需要注意下,那就是 Redis 的键设计。

代码中的 __keyevent@0__:expired 频道匹配意味着,编号为 0 的库中所有键过期时间都会被订阅到。而这个 Redis 可能不单单只有这个业务在使用,有可能存在其他的业务也在使用。总不可能来个任意的键都会需要去做过期处理。最好是有个通用的设计规则,对 Key 的含义分割。比如:产品固定前缀:业务:业务属性:业务唯一标识

app1:trans:notice:1615283234

代表:系统名为 app1 的 在交易模块 的 订单号为 1615283234 的通知业务的消息。当监听器解析 Key 失败时则说明是其他的键过期,不做处理。一旦解析成功,则对消息进行路由分发。

键搞定了,值就看业务情况而定。如果是通知的话,必须带上当前是第几次通知,根据这个再加上策略才能算出下次通知时间(该键的过期时间)。

一般简单的方法都存在多少的缺陷,这种方式也不例外。引用 Redis 官网的一段话:

Because Redis Pub/Sub is fire and forget currently there is no way to use this feature if your application demands reliable notification of events, that is, if your Pub/Sub client disconnects, and reconnects later, all the events delivered during the time the client was disconnected are lost

意思是说:Redis 目前发布订阅基于 发送即忘 策略,且没有 ACK 机制,意味着客户端重启掉线期间,消息会丢失。加上 Pub/Sub 消息 没有持久化机制,假如当订阅客户端由于网络原因没收到,想再次重试,这是没法实现的。

假如此时我还想跟内存队列那样子能够 对消息的延迟时间进行自动排序,该如何实现呢?除此之外,Pub/Sub 是广播机制,假如存在多个订阅者,那么就会 同时收到键过期的消息,此时又该如何处理 消息竞争 问题?

基于 Sorted Set 实现

这时候我们要引入 Redis 的 Sorted Set 数据结构。关于这个数据结构简单来说是 支持排序的 Set,靠的是与之关联的浮点值,称为 score 来实现的。值得注意的是,这个排序并不是放进去的时候排,是拿出来的时候(联想到 性能 问题,后面有讲)。这里引用一段官网的话:

Moreover, elements in a sorted sets are taken in order (so they are not ordered on request, order is a peculiarity of the data structure used to represent sorted sets).

所以我们只需要将消息延迟执行的时间戳作为分数值,就能解决上文所说的排序问题,当然由于该结构是 Redis 的基本功能,自然也支持持久化,也就是解决了消息丢失问题。

大概设计如下:

异步结果通知实现——基于Redis实现,我这操作很可以

首先看看,消费者线程该如何实现(SpringBoot 环境下)

@Slf4j
@Component
public class ConsumerTask {
    @Autowired
    RedisTemplate<String, Object> redisTemplate;
	// Sorted Set 队列键 
    private static String KEY = "TEST:ZSET";
    
    @Scheduled(cron = "0/1 * * * * ?")
    public void run() {
        try {
            this.doRun();
        } catch (Exception e) {
            log.error("消费异常", e);
        }
    }
    
    private void doRun() {
    	// zrange 分数从小到大 zrevrange 分数从大到小
        // 拿出最新的待处理消息
        Set<ZSetOperations.TypedTuple<Object>> tuples = 
        redisTemplate.opsForZSet().rangeWithScores(KEY, 0, 0);
        if (CollectionUtils.isEmpty(tuples)) {
            log.info("队列无数据");
            return ;
        }

        ZSetOperations.TypedTuple<Object> typedTuple = tuples.iterator().next();
        if (typedTuple == null) {
            log.info("队列无数据");
            return ;
        }
        Double score = typedTuple.getScore();
        Object value = typedTuple.getValue();
        
        if (System.currentTimeMillis() < score) {
            log.info("未到执行时间...");
            return ;
        }

        Long zrem = redisTemplate.opsForZSet().remove(KEY, value);
        if (Long.compare(1L, zrem) == 0) {
            log.info("删除数据成功,开始处理,数据:{}", value.toString());
            
            // do someting...
            
            // 假如通知失败,需要重新计算通知时间(score 值)并在 Redis 设置(ZADD)该消息
        }
        else {
            log.info("被其他的消费端抢占,不处理...");
        }
    }
}

跟之前的 推模式 相比,这次采用的是 拉模式,尽管在多个消费端可能同时拿到同一个消息,不过这里通过 Long zrem = redisTemplate.opsForZSet().remove(KEY, value) 这方法,利用了 rem 命令的原子性 解决了竞争问题,也就是说只会有一个客户端删除成功。

仔细观察的话,可以看到我们拿到的时间戳是 Long 类型的,但是 Spring 提供的 Sorted Set 操作 api 参数是 Double 类型

org.springframework.data.redis.core.ZSetOperations#add(K, V, double)
org.springframework.data.redis.core.ZSetOperations#rangeByScore(K, double, double)

那会不会有精确丢失问题?所以输出看下最大最小值

System.out.println(Long.MAX_VALUE); // 2 的 64 次方-1,19 个数位
System.out.println(Long.MIN_VALUE); // 负的 2 的 64 次方 
System.out.println(Double.MAX_VALUE); // 2 的 1024 次方 -1,308 个数位
System.out.println(Double.MIN_VALUE); // 2 的 -1074次方 

可以看到 Double 最大值远远大于 Long 类型,加上时间戳不会有负数,所以可以放心转换。

在这里不演示生产者代码,过于简单,就是调用 zadd 命令而已。这里也需要注意,如果是异步通知场景 zadd 的值必须带上这是第几次通知,就如前面的方案一样。

到此为止,第一种方案存在的问题在第二种方案全部解决了。下面看一种网上的比较多的实现方式。

基于 Sorted Set、List 实现

跟上一种相比多了一个 List 数据结构。先来看下加入 List 之后的整个设计图

异步结果通知实现——基于Redis实现,我这操作很可以

不得不说刚开始看见这种方案时,是存在疑惑的。因为上面的 Sorted Set 已经实现了功能,为什么要引入 List 数据结构增加系统的复杂度?唯一能看到的好处就是 List 数据结构提供了 阻塞 操作?经过与同事讨论后,得出下面几点结论:

  • 客户端拉取消息 控制并发的步骤减少。当使用 List 时,只需要调用一个命令就可以解决消息竞争问题,而使用 Sorted Set 则需要使用 zrange 和 zrem 两条命令来实现,相比之下,多交互一次网络,且实现更复杂。
  • 客户端拉取消息的方式增多,同时,队列提供 阻塞式 访问,同样也 减少 了客户端由于无限循环造成的 CPU 浪费。
  • 队列 pop 操作比 zrange 操作对 Redis 来说性能开销更小,在这种频繁拉取的情况下更加合适。

这里需要注意的一点是,搬运操作有多个命令一起完成,如下伪代码:

// 1、从 Sorted Set 中拿出 score 值在 前五秒 到 目前(包含现在)的所有元素
Date now = new Date();
Date fiveSecondBefore = DateUtils.addSeconds(now, -5);
Set<Object> objects = redisTemplate.opsForZSet()
.rangeByScore("Sorted Set:Key", fiveSecondBefore.getTime(), now.getTime());
if (CollectionUtils.isEmpty(objects)) {
	return ;
}
// 2、将这些元素从 Sorted Set 中删除
Long removeResult = redisTemplate.opsForZSet().remove("Sorted Set:Key", objects);
if (Long.compare(removeResult, objects.size()) != 0) {
	return ;
}
// 3、将这些元素放进 List
Long result = redisTemplate.opsForList().leftPushAll("List:Key", objects);

rangeByScore、remove、leftPushAll 这几个操作不具有原子性,可能在中途发生异常、宕机等情况,导致在搬运过程中丢失或重复搬运。
好在 Redis 提供了执行 lua 脚本功能,会保证同一脚本以原子性(atomic) 的方式执行,所以我们只需要原子性操作的多个步骤整合在自定义 lua 脚本中即可,如下:

local list_key = KEYS[1];
local sorted_set_key = KEYS[2];
local now = ARGV[1];
local sorted_set_size = redis.call('ZCARD', sorted_set_key)

if (tonumber(sorted_set_size) <= 0) then
    return
end

local members = redis.call('ZRANGEBYSCORE', sorted_set_key, 0, tonumber(now));
if (next(members) == nil) then
    return
end

for key,value in ipairs(members)
do
    local zscore = redis.call('ZSCORE',sorted_set_key,value);

    if (tonumber(now) < tonumber(zscore)) then
        return zscore;
    end

    redis.call('ZREM', sorted_set_key, value);
    redis.call('RPUSH', list_key, value);
end

local topmember = redis.call('ZRANGE', sorted_set_key, 0, 0);
local nextvalue = next(topmember);
if (nextvalue == nil) then
    return
end

for k,v in ipairs(topmember)
do
    return redis.call('ZSCORE', sorted_set_key, v);
end

下面是 SpringBoot 定时调用该 lua 脚本进行搬运的示例代码:

@Scheduled(cron = "0/1 * * * * ?")
public void run4() {
    ClassPathResource resource = new ClassPathResource("sorted_set_to_list.lua");
    String luaScript = FileUtils.readFileToString(resource.getFile());
    DefaultRedisScript<String> redisScript = new DefaultRedisScript<>(luaScript, String.class);
    //
    List<String> keys = Lists.newArrayList("TEST:LIST", "TEST:ZSET");
    String now = String.valueOf(System.currentTimeMillis());
    // 注意这里的序列化器,需要换成 StringSerializer
    // 替换的默认的 Jackson2JsonRedisSerializer
    String executeResult = redisTemplate.execute(redisScript, redisTemplate.getStringSerializer(),
            redisTemplate.getStringSerializer(), keys, now);
    log.info("lua 脚本执行结果:{}", executeResult);
}

最后再来看看消费者该如何实现

@Component
@Slf4j
public class ListConsumer implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        Executors.newSingleThreadExecutor().submit(new PopEventRunner());
    }
    private static class PopEventRunner implements Runnable {
        @Override
        public void run() {
            RedisTemplate<String, Object> redisTemplate  = (RedisTemplate<String, Object>) SpringUtil.getBean3("redisTemplate");
            while (true) {
                try {
                    Object leftPop = redisTemplate.opsForList().leftPop("TEST:LIST", Integer.MAX_VALUE, TimeUnit.SECONDS);
                    if (leftPop == null) {
                        continue ;
                    }
                    // do something...

                    // 当通知失败时,重新计算通知时间并设置(ZADD)Redis
                } catch (Exception e) {
                    log.error("监听异常", e);
                    sleep(5); // 发生异常睡五秒
                }
            }
        }
    }
}

监听容器的刷新事件,创建监听单线程,无限循环阻塞监听队列。相对于前一种实现方案,该方案确实更加的贴合。但仍有优化的余地,比如:

  • 搬运线程的时机,目前频率为 1 秒,所以极端情况会有 1 秒时间的延迟。且在 Sorted Set 为空情况下,对 CPU 是一种浪费。

小结

相对前一篇内存实现,Redis 这种方式更加的可靠,且在允许一点时间的误差和牺牲一点消息可靠性下,不失为一种 性价比高 的选择。假如当前景就是不允许有这些损失,那还有什么解决方案吗?到时候我们再来讲终极杀招,使用 RabbitMQ 来实现。

Redis应用3-基于Redis消息队列实现的异步操作 Redis实现消息队列的模式常用的消息队列有RabbitMQ, ActiveMQ, Kafka等,这都是开源的功能强大的消息队列,适合于在企业项目应用。Redis实现的消息队列代码原理 Redis提供了两种方式来作消息队列。 一个是使用生产者消费模式模式, 另一个就是发布订阅者模式。 前者会让一个或者多个客户端监听消息队列,一旦消息到达,消费者马上消费,谁先抢到算谁的,如果队列 阅读详情

相关推荐

Laravel5.6使用redis队列实现系统通知

需求: 一、我们这个系统通知模块的功能是后台发送一个系统通知给所有人或者是给一个人。比如我们在8月8号发送一个系统通知:欢迎大家来到武汉PHP培训长乐未央学习技术。那么每一个人都会收到这个通知,但是如果是8月9号注册进来的人就不会收到这个通知。这个时候,这种通知必须是分发的,每个人都需要有一条记录来保存所分发的通知,所以这是一个分发的逻辑。 二、使用同步还是异步来分发。比如我们要是群发的话,需要工作人员在后台点击发布按钮就同步发送通知到用户的通知箱呢还是异步使用队列来做这个事情,当然选择异步更加稳妥。它能防

huangdj321的博客 631

异步结果通知实现——基于Redis实现,我这操作很可以

大概逻辑:当首次通知、或通知失败时,设置(重新设置)在 Redis 对应的 Key 的过期时间,Redis 会监听过期事件,发生事件时通知订阅者,订阅者接收到事件,做逻辑处理。所以我们只需要将消息延迟执行的时间戳作为分数值,就能解决上文所说的排序问题,当然由于该结构是 Redis 的基本功能,自然也支持持久化,也就是解决了消息丢失问题。监听容器的刷新事件,创建监听单线程,无限循环阻塞监听队列。相对前一篇内存实现,Redis 这种方式更加的可靠,且在允许一点时间的误差和牺牲一点消息可靠性下,不失为一种。

m0_63437643的博客 534

ZKmall模板商城微信支付异步通知幂等性设计与实现

在电商交易场景中,微信支付异步通知的幂等性设计是保障资金安全与数据一致性的核心环节。ZKmall模板商城基于其模块化架构与Spring Cloud Alibaba生态,通过等策略,构建了一套高可靠的异步通知处理体系。

1166

RedisTemplate常用集合使用说明-opsForZSet(六)

1、add(Kkey,Vvalue, doublescore) 添加元素到变量中同时指定元素的分值。 Java代码 redisTemplate.opsForZSet().add("zSetValue","A",1); redisTemplate.opsForZSet().add("zSetValue","B",3); redisTemplate.opsFo...

qq_39071667的博客 5万+

后端开发中 Spring Data Redis 的异步操作实现

本文旨在解析 Spring Data Redis 框架中异步操作的核心机制,覆盖从基础 API 使用到底层网络协议栈的全链路实现原理。重点讨论在高并发场景下如何通过异步非阻塞模型提升系统吞吐量,并提供可落地的工程实践方案。核心概念:对比同步/异步模型,解析 Reactor 模式算法原理:深入 Lettuce 事件循环和 Netty 线程模型实战案例:电商库存异步扣减系统完整实现性能分析:不同并发量下的 QPS 对比测试Lettuce。

架构师的AI之路,分享AI应用开发架构的学习与实践。 1045

大学物理第二章 质点动力学详解

大学物理第二章 质点动力学概念详解

weixin_63026364的博客 1万+

redistemplate hash 过期时间_Redis开发 —— 过期消息通知实现(Springboot)

实际在我们开发过程中,有一些业务场景需要能够在一段时间之后能自动变更数据状态,如优惠券,特价商品,购物车等,这个时候如果实现基于redis,就可以使用下面的方案。一,在系统添加配置类import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configurati...

weixin_39634132的博客 950

有史以来最小的GIF/png/jpg/jpeg

昨天我对图像进行了 base64 编码,这样我就可以将它发送到 CouchDB 以测试我正在为客户编写的一些代码。它让我想起了我之前在远程服务器上设置 cookie 时所做的事情。基本上,一个小的 PHP 脚本被放在远程服务器上,它接受几个 GET 参数并根据它们的值设置一些 cookie。然后脚本输出一个 1x1 的透明 GIF。本地服务器上的 PHP 脚本生成了一个 IMG 标签,该标签链接到该图像并根据本地服务器上的 COOKIES 设置参数。

凌凌1301的博客 1416

异步结果通知实现-整体介绍与内存中实现

异步结果通知实现-整体介绍与内存中实现 转发自:https://juejin.cn/post/6936802804937785351 上图是目前扫码支付中普遍的数据流转情况。在此场景中,异步结果通知 承担着保证两系统(支付渠道和商户)之间 数据一致性 的工作。当有支付结果时,为保证时效性,必须 立即 通知给下游商户,且当通知失败时需要尽量保证系统间数据一致性,即遵循约定的 重试策略。由此可以看出是十分重要的一个环节。 关于异步通知的实现,本人结合实际经验和网上一些业界流行的解决方案,整理出了几篇相关的笔记

qq_38205881的博客 783

CISSP/CCSP证书到手后别松懈!保姆级维持攻略:CPE积分怎么攒?年费怎么交?

本文为CISSP/CCSP持证者提供详细的维持认证攻略,重点介绍如何高效积累CPE积分和避免年费缴纳中的常见问题。通过免费与付费资源结合的策略,帮助持证者轻松完成年度认证要求,同时利用认证创造职业价值。

weixin_30859423的博客 415

Halcon和C#联合编程实现硬币识别(个人入门练习)

本人为机器视觉入门小白,自己突发奇想 1.图片数据来源和分析 2.HALCON实现 3.C#搭建界面框架 4.C#中嵌入HALCON代码,即联合编程 5.导出.exe文件,运行以及Debug 目标是这样的,在图片中识别出每种类型的硬币数量,然后计算出总钱数。先上结果,再细说过程。 C#界面和识别结果: 1.图片数据来源和分析 图片大小及格式均统一,拍摄的时候已经尽可能的去除了背景噪点,所以图像处理的要求并不很高(重点在于思路)。硬币区分原理本人代码采用直径范围来判断(也可以半径或区域面积,HALCON算子

Demobird的博客 3614

Laravel + Redis 实现异步事件处理与 Redis 队列最佳实践

Laravel + Redis 异步事件处理方案 本文详细介绍了使用 Laravel 和 Redis 实现高效异步事件处理的方案。主要内容包括: 环境配置:安装 Redis 服务,配置 Laravel 项目以使用 Redis 队列驱动 实现步骤: 创建事件类和异步监听器 注册事件与监听器关系 使用事件触发异步任务 队列管理: 使用 Supervisor 管理队列工作进程 队列任务监控和失败处理机制 高级配置如优先级队列和任务超时设置 最佳实践: 合理的队列命名策略 任务重试与失败处理机制 性能优化建议 相比

Tekin 是深耕技术 20 年的全栈实战派专家,精通 Go/Python/Java 等多语言开发。博客专注技术原理与实战结合,深度解析 Python 高阶编程、Go 语言架构、数据库优化等硬核内容。涵盖并发编程、机器学习、云原生等前沿领域,通过真实案例拆 2211

RTA_OS基础功能讲解 2.6-资源锁和自旋锁

访问需要在任务和 ISR 之间共享的硬件或数据可能不可靠、不安全。这是因为当优先级较低的任务或 ISR 正在更新共享数据时,可能会发生任务或 ISR 抢占。这种情况被称为竞争条件,极难测试。访问共享数据的语句序列称为关键部分。要安全访问关键部分中引用的代码和数据,就需要执行互斥。换句话说,必须确保系统中没有其他任务或第 2 类 ISR 能够在关键部分期间抢占正在执行的任务。你可以将任务声明为非抢占式任务,这样就可以避免互斥问题。

本博客专注于嵌入式软件领域技术分享。 290

Flask+Celery+Redis实现队列化异步任务

概述: 我们考虑一个场景,公司有一个需求,现在需要做一套web系统,而这套系统某些功能需要使用一些开源工具的sdk和api,或是运行一些耗时比较大的任务(单个大任务下可能有多个小任务),需要一段时间才能提供执行结果,而前端同事要求不能让用户在页面等待,需要马上提供一个返回结果给他,任务执行完后可以拿到最终结果,并且用户退出web界面或浏览器异常关闭之后,再次返回界面,执行的过程不会中断,并且支持多用户同时执行不同操作的需要。 很明显,这是一个-异步多线程-的场景,在Pyt...

qq_41905051的博客 1万+

8、音频运行时系统的架构设计

本文深入探讨了音频运行时系统的分层设计及其优势,包括逻辑层和物理层的功能划分。通过分层设计,开发者可以更轻松地管理和优化音频资源,确保其在不同平台上的高效运行。文章还介绍了平台适配与优化、错误处理与调试以及未来发展方向等内容,为开发者提供了宝贵的参考和指导。

juice的博客 461

微信小程序 - [wxapplib]] backgroundfetch privacy fail {“errno”:101,“errMsg”:“private_getBackgroundFetchDa

微信小程序报错之backgroundfetch privacy fail,微信小程序报错WAServiceMainContext.js:1 [wxapplib]] backgroundfetch privacy fail {“errno“:101,怎么解决?问题出现:调用wx.chooseMessageFile报错(开发者工具中正常)用户隐私协议中未声明小程序使用此功能,安卓真机调试报错:backgroundfetch privacy fail ,怎么解决?微信小程序[wxapplib]] backgrou

🏆 前端领域优质创作者 1万+

Redis100篇 - Redis的Key过期通知 实现定时任务的技巧

本文介绍了如何利用Redis的Key过期通知功能实现高效定时任务,替代传统的轮询方案。主要内容包括: 核心优势:Redis过期通知通过事件驱动实现毫秒级触发,避免了轮询带来的延迟和资源浪费。 实现原理:Redis采用惰性删除+定期删除策略,通过配置notify-keyspace-events Ex开启过期事件通知。 实战开发: 配置Redis服务端开启通知功能 使用Spring Boot集成Redis消息监听 通过MessageListener接收处理过期事件 典型应用:订单超时取消、缓存自动清理等场景,相

千淘万漉虽辛苦,吹尽狂沙始到金 2万+

解决微信小程序长页面滚动到底部点击底部的输入框后输入框漂浮且页面滚动到顶部

一、问题描述 项目中有一个长页面上部展示部分信息下部为信息录入,页面长度为三屏幕(不同手机屏幕大小略有差异),当滚动到第二屏或者第三屏去填写信息时点击输入框后输入框漂浮起来了并且页面向上滚动了一段距离,回到了第一屏中展示的内容。效果如图。 滚动到第二屏,证件号输入。 点击输入框 可以看到证件号输入框漂浮了起来并且页面滚动到了第一屏展示的内容。 注意:小程序是2018年上线,在2020年4月份之前该页面从未出现过这种现象。推测:微信的后续更新中对微信小程序基础库进行了重构,导致点击输入框后页

仰望星空的代码 3255

springboot中使用redis实现异步消息通知

为什么我要用redis来完成异步消息,而不是消息队列mq之类的? 因为很多的单体项目可能只需要需要一个略微简单的消息通知,而不需要如kafka那种完善的消息队列, 而且redis在正常的项目中基本都会引入而mq可能较少会引入,所以使用redis来实现消息通知可以减少不必要的中间件引入和维护.   设计思路的来源 主要借鉴了spring对jms的封装,比如使用注解@JmsListener来完...

cdy1996的博客 4396

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

分享如何通过Mq、Redis、XxlJob实现算法任务的异步解耦调度

欢迎讨论交流~

m0_74969835的博客 1545

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

RabbitMQ 延迟队列实现订单支付结果异步阶梯性通知

场景 在第三方支付中,例如支付宝、或者微信,对于订单请求,第三方支付系统采用的是消息同步返回、异步通知+主动补偿查询的补偿机制 1.商户请求交易接口成功。 2.接受银行的异步通知。 3.处理业务,将通知URL和通知的数据放到队列中。通知队列是常驻的。 4.如果通知商户成功/失败更新通知状态。如果通知失败,根据通知间隔重新把通知数据放到通知队列里。 5*(2^n-1)秒后再次通知,n指回调...

weixin_34268310的博客 577

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

【三方调用】如何实现异步通知的重试机制

工作中经常要和第三方做对接,比如支付、电子合同等系统。操作成功之后,第三方会发送异步的通知,返回最终的处理结果,使用异步而不是使用同步通知,是为了加快系统响应速度,防止线程阻塞。任务处理完成后通过异步的通知,发送给对应的服务端。之前对接微信支付,完成支付后,微信发送一个异步通知给服务端,服务端根据支付通知修改状态,通知规则看到以下的一段话。

DreamSun的博客 949

java redis 异步更新

Java Redis 异步更新的实现指南 在现代应用开发中,随着数据处理需求的不断增加,如何高效地进行数据更新成为了一个重要课题。Redis作为一个高性能的内存数据存储工具,非常适合用于存储和更新数据。本篇文章将引导你实现Java和Redis的异步更新,适合刚入行的小白,以帮助你掌握这一技能。 流程概览 在实现Java R...

weixin_40364466的博客 337

【Python3】异步操作 redis

aioredis 在高版本已经不支持了, 不要用代码示例测试接口这将会在 Redis 中存入键为 my_key,值为 my_value 的数据。这将返回 Redis 中 my_key 对应的值,应该是 my_value。

言之。 1万+

消息队列异步请求,客户端同步收到结果

如何设计一个接口,使用消息队列异步请求,但是客户端同步收到结果   异步处理,同步返回?为什么会有这样一个需求?既然接口要求同步返回,那么直接阻塞就好了,要什么异步消息同步返回?高并发保护系统的手段是缓存、限流、降级。限流有许多的手段,想令牌桶、漏桶算法按数量限流,也有使用消息队列,排队限流的。至于使用消息队列的好处就不多说了,这里主要将如何实现这个需求,有一个系统比较的不稳定,但是没人维护,又不能替换它,只能在他的上层加一层来保护她,可以限流处理,也可以用mq让它以他的最大处理能力处理。说白了这东西就是

Baron_ND的博客 3532
上一篇: 限量首发!Alibaba首次公开“Java成长笔记”,看了后直呼差距真的不止一点点
下一篇: 拆开了揉碎了跟你说清楚,对乱糟糟的“日志”说再见!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值