背景

多数的移动端APP都会有做任务领取奖励的功能模块,这类需求的目的是培养用户使用习惯,提升用户活跃性,用户完成任务获得积分奖励,通过积分兑换商品或者充值话费,微信体现等。

拟定需求场景(如图↓),概要:APP底部导航中新增小任务Tab,点击Tab可查看任务完成进度和领取情况,点击去完成跳转到做任务的业务界面,当用户完成任务并且满足领取条件的时候,任务Tab需要红点提醒用户当前有奖励可领取,用户领取后并且当前没有待领取奖励小红点消失,任务完成进度和领取状态仅保持当天,隔天刷新。

业务分析

在开发前需要对需求进行整理,对细节进行确认,然后设计解决方案,预估开发时间,这里将对于业务中核心的内容进行梳理:

用户想要完成任务,需要去操作其他业务功能,如:评论成功后需要完成每日评论任务,关注主题后完成关注新手任务,这里就涉及核心问题,任务需要依赖于其他业务

为了保障后续拓展性,任务需要支持后台管理,配置任务名,描述,任务类型(每日,新手,活动),完成次数,奖励积分数量,去完成跳转uri 等

用户完成任务后不用自动领取奖励,需要进入到任务列表点击领取操作,可领取时导航Tab需要小红点提醒,和产品确认任务的完成和提醒的用户体验 可以接受短时间延迟

用户多次操作业务,或者出现重复操作(恶意并发请求刷积分),保证任务只能完成一次并且只能领取一次奖励,需要保证幂等性

方案设计

核心目标:

任务依赖其他业务,需要进行解耦,不影响其他业务的功能和性能

设计后台可管理,便于后续拓展

抽象任务模块,代码抽象开发

完成任务和领取需要保证幂等性

高可用

名词定义:

事件

任务中涉及依赖其他业务,这里需要抽象出一个概念,用户通过操作业务,完成任务的这个操作,我们把这个过程定义为用户完成任务事件触发完成,如:评论事件,点赞事件,关注事件,等

解决方案:

在实现方案上,采用异步消耗队列的方式,依赖业务接口埋入事件上报,将用户成功操作业务的任务事件上报到队里中,然后开发消息消耗的脚本程序,对消息中用户触发的任务事件进行业务逻辑处理和DB操作,更新用户任务进度和可领取状态,响应给用户(完成任务红点提醒),设计图:

依赖业务解耦

依赖业务将操作成功用户的任务事件上报到消息队列,然后程序进行异步消耗

方案解决了依赖业务之间的强耦合,并且基本不影响现有依赖业务的接口性能

高可用:

通过调度系统启动多进程对队列进行消耗

进程守护系统,守护进程保活,奔溃重启,可对执行日志进行记录与查看

消息队列监控,无法及时消耗进行预警,保障即时性,避免长时间的延迟

rabbitmq

redis list

... ...

容错与补偿

队列消耗失败需要进行记录,并可根据业务场景,通过另外程序进行补充处理

用户操作业务上报任务事件不限制次数,以免用户没完成任务,允许用户重新尝试去做任务,程序消耗需要控制任务只能完成一次

表结构:

-- 任务表

CREATE TABLE `task` (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增',

`icon` varchar(300) NOT NULL DEFAULT '' COMMENT '图标',

`title` varchar(30) NOT NULL DEFAULT '' COMMENT '任务标题',

`type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '任务类型,新手任务=1,每日任务=2',

`event` int(11) NOT NULL DEFAULT '0' COMMENT '事件',

`des` varchar(30) NOT NULL DEFAULT '' COMMENT '任务描述',

`target_num` int(11) NOT NULL DEFAULT '0' COMMENT '目标数量',

`points` int(11) NOT NULL DEFAULT '0' COMMENT '金币',

`sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',

`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态 0=下线,1=上线,-1=删除',

`app_version` varchar(15) NOT NULL DEFAULT '' COMMENT 'app版本号',

`app_version_compare` varchar(10) NOT NULL DEFAULT '' COMMENT 'app版本号比较运算符',

`operator` varchar(10) NOT NULL DEFAULT '' COMMENT '操作人',

`jump_uri` varchar(300) NOT NULL DEFAULT '' COMMENT '跳转协议',

`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

`update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',

`event_begin` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00' COMMENT '事件开始时间',

`event_end` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00' COMMENT '事件结束时间',

`task_begin` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00' COMMENT '任务开始时间',

`task_end` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00' COMMENT '任务结束时间',

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 用户任务情况表

CREATE TABLE `user_task_case` (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户任务情况',

`user_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '用户ID',

`task_id` int(11) NOT NULL DEFAULT '0' COMMENT '任务id',

`task_type` int(11) NOT NULL DEFAULT '0' COMMENT '任务类型',

`event` int(11) NOT NULL DEFAULT '0' COMMENT '事件',

`task_uni` varchar(30) NOT NULL DEFAULT '' COMMENT '任务唯一标识(唯一约束) ',

`target_num` int(11) NOT NULL DEFAULT '0' COMMENT '目标数量',

`finish_num` int(11) NOT NULL DEFAULT '0' COMMENT '完成数量',

`points` int(11) NOT NULL DEFAULT '0' COMMENT '可领取金币数量',

`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态 0=待完成,1=待领取,2=已经领取',

`finish_at` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00' COMMENT '完成任务时间',

`get_at` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00' COMMENT '领取时间',

`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

PRIMARY KEY (`id`),

UNIQUE KEY `uni_user_id_task_uni` (`user_id`,`task_uni`) USING BTREE,

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户任务情况表';

更新语句:

-- 更新领取状态,注意:WHERE条件,强校验

UPDATE user_task_case

SET `status`=2,finish_at=CURRENT_TIMESTAMP

WHERE id=:id AND user_id=:user_id AND `status`=1 AND finish_num>=target_num

表重点字段说明:

task_uni

任务唯一标识

user_id和task_uni 组合唯一约束索引

每日任务:

任务id_任务类型_日期(task_id_type_date)

默认都是只做一次(新手任务/活动任务):

任务id(task_id)

幂等性

user_task_case 表中 user_id和task_uni 组合唯一约束索引,通过mysql的唯一约束,保证了多进程并行消耗事件队列的情况下,每日任务和一次性任务不能重复INSERT

通过UPDATE的WHERE条件校验保障领取的幂等性

管理后台:

产品在规划需求的时候会设计出相关后台,但是不一定设计的合理,所以这里需要根据确认的解决方案协助产品对于管理后台进行调整,保障后续的拓展性

代码层面:

面向抽象开发,合理使用设计模式,便于后续的拓展

话外篇:

谈近一年的感悟,近一年参与了新APP项目的开发,从0开始搭建项目,看着DAU一点点儿的涨起来,还是挺有成就感的。

角色上产生了变化,现在感觉自己更像是一个项目的参与者,而不是任务的执行人,完成业务开发的同时也会对产品上有根深了解。

空闲时间也会对竞品调研以及用户使用意见或者问题进行跟进,站在用户角度提供产品上的一些建议。

后续会把新项目开发过程中遇到问题或者常见的业务场景下的解决方案进行梳理出来进行博文分享。

首发于Github : [

JAVA常见业务参加解决方案_大话业务场景与解决方案-做任务相关推荐

  1. 人工智能+智能运维解决方案_如何建立对人工智能解决方案的信任

    人工智能+智能运维解决方案 I interviewed Marisa Tschopp who is an organizational psychologist conducting research ...

  2. 数据查询和业务流分开_内销业务管理解决方案

    内销业务管理解决方案 内销系统是以货物流为基础,以票据流为主线,以资金流为补充的3种数据流关于进货.库存.销售和财务的管理系统.它可以降低企业的库存,提高资金利用率和结算速度,实现管理的高效性.实时性 ...

  3. java抛异常 代替返回_请问业务层方法是抛出一个异常好还是返回一个结果更好...

    @Override public Response checkUserToken(long uid, String accessToken, String deviceToken){ Response ...

  4. 大数据业务学习笔记_学习业务成为一名出色的数据科学家

    大数据业务学习笔记 意见 (Opinion) A lot of aspiring Data Scientists think what they need to become a Data Scien ...

  5. java常见的hash算法_常见的哈希算法和用途

    写在前面 哈希算法经常会被用到,比如我们Go里面的map,Java的HashMap,目前最流行的缓存Redis都大量用到了哈希算法.它们支持把很多类型的数据进行哈希计算,我们实际使用的时候并不用考虑哈 ...

  6. java常见的gc回收器_一篇文章让你了解GC垃圾回收器

    简单了解GC垃圾回收器 了解GC之前我们首先要了解GC是要做什么的?顾名思义回收垃圾,什么是垃圾呢? GC回收的垃圾主要指的是回收堆内存中的垃圾对象. 从根对象出发,所有被引用的对象,都是存活对象 其 ...

  7. java常见的排序算法_常见排序算法及Java实现

    先上个总图↓: ①.直接插入排序 插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并 ...

  8. 气象gis 解决方案_杜邦可持续解决方案全方位智能化应急管理系统解决方案

    随着我国改革开放的不断深化,从国家政策支持.经济建设需要.和行业技术发展等方面,石油化工行业迎来了发展的黄金时期,化工企业逐渐向大型炼化一体化企业或综合型化工园区方向发展.虽然大型化和集中化模式在运营 ...

  9. java服务自动降级方案_在京东我们是如何做服务降级的

    当我们依赖的中间件资源或者是上游服务性能出现严重问题时,为了防止用户看到错误页面或者加载页面时间过长,我们需要将服务降级静态页面.或者将不影响主流程的旁路服务关闭掉,以让出资源给主要流程.这类操作称为 ...

最新文章

  1. 皮一皮:你住的小区叫什么名字?
  2. python【力扣LeetCode算法题库】55-跳跃游戏
  3. 【经验心得】CS1.6:经典中的精品
  4. vim中设置python代码缩进为4个空格
  5. JZOJ 5820. 【NOIP提高A组模拟2018.8.16】 非法输入
  6. 重磅亮相KubeCon China,腾讯云为你揭秘国内云商最大容器集群
  7. Win7系统隐藏文件恢复的方法
  8. 下划线_Python中下划线的5种含义
  9. EularProject 39:给周长推断构成直角三角形个数
  10. Search Engine -垂直搜索小汇总
  11. Nginx配置与安装及发布项目
  12. fluent瞬态计算终止条件在哪里设置_基于商用软件FLUENT的LES(大涡模拟)计算教学...
  13. POM文件详解(如何组织POM文件)
  14. 【模拟】1177.正方形
  15. DialogFragment的OnDismissListener
  16. Clock skew detected. Your build may be incomplete
  17. 一位博士在华为的 22 年
  18. 腾讯短网址/短链接url.cn生成接口工具推荐
  19. 当年明月、袁腾飞、阎崇年三人的专业水平的比较以及由此想到的一些学习方法、品书原则
  20. C4droid安装使用教程

热门文章

  1. android 动画结束停留,循环动画 tween durationMillis = 90195 动画将停留在最后一针
  2. php5.4.13.tar.bz2,编译安装PHP-5.4.13
  3. java jsr305_java – 为什么我需要添加神器JSR305才能使用Guava 14?
  4. STM32F405 HAL库 STM32CUBE开发
  5. java锁包读写锁_java8读写锁如何使用
  6. pytorch实现基本AutoEncoder与案例
  7. linux bash gt,linux之bash的基础特性(一)--gt;命令历史(history命令),命令补全,路径补全...
  8. 吉林省高等学校计算机水平考试,关于2014年11月高等学校计算机水平考试(吉林省考区)报名的通知...
  9. c语言二维数组总成绩,c语言5个人3科成绩总分和平均分,用二维数组
  10. supersu二进制更新安装失败_Q音直播编译优化与二进制集成方案