不逼自己一把都不知道自己还能这么优秀(小鹅通学习记录大批量队列同步)

简介: 不逼自己一把都不知道自己还能这么优秀(小鹅通学习记录大批量队列同步)

前言

对于非程序员来说,程序员的代码可能会具有神秘感,因为大多数人并不了解程序员使用的编程语言和技术细节,也无法理解程序员在编写代码时所面临的各种难题和思考过程。而程序员所编写的代码在计算机上运行的方式也比较神秘,大多数人无法看到代码运行时产生的中间过程和结果。这些因素可能会给人一种神秘感。


不过,对于程序员来说,代码并不具有神秘感。对于他们来说,编写代码是一种常规的工作,需要不断地分析问题、思考解决方案并将之转化为代码实现。他们了解编程语言和技术细节,并能够理解代码中所涉及的各种变量、数据类型和逻辑关系等。在写代码时,程序员也会在新旧代码之间进行调试和优化,进一步减少代码的神秘感。


虽说对于程序员来说,代码不是神秘的东西,而是一种常规的工作产物,但是在其中不断突破和成长的过程,确实每每都有一种收获感和成就感。


一、编程语言介绍

1.php是世界上最好的语言

“php是世界上最好的语言”。PHP是在web开发中被广泛应用,它具有较好的稳定性和开发效率,同时也有较为完善的开发工具和社区支持。但是,PHP也有一些缺点,比如说它的性能相对较低,对于大型复杂项目的开发可能不太适合。


但是,对于web开发,综合考虑项目需求、技术特点和资源情况等因素,追求低成本、高效率的实用主义者来说,我已经上船了,下不来了。


2.第三方API对接的苦恼

而在php开发中最为头疼的就是和第三方API对接,头发量的密度几乎和开发时间进程长度成反比例增长。在对接第三方API接口时,常见的问题包括以下几点:


  1. 认证问题:第三方API需要认证才能够使用,这就需要程序员提供相应的认证信息,并进行认证操作。在认证时,需要注意提供的认证信息是否正确,是否符合API接口的要求,否则可能会导致认证失败。
  2. 参数问题:调用API接口时,需要设置请求参数、请求头等,在设置时需要注意参数的格式和值是否符合API接口的要求,否则可能会导致请求失败。
  3. 接口返回格式问题:有些第三方API可能会返回各种格式的数据,如XML、JSON等,需要程序员进行相应的数据解析和处理才能使用。在处理时需要注意数据格式是否一致或者是否需要进行转换。
  4. 超时问题:在调用API接口时,可能会遇到请求超时或者返回数据超时的情况,需要设置相应的超时时间或者进行错误处理,以避免程序因超时问题而中断。
  5. 安全问题:在使用第三方API时,需要注意数据的安全性,如密码等敏感信息需要按照API接口要求进行加密或者隐藏,以保护数据的安全。


3.为什么说好的项目进度表都是画饼

“我从没按照项目进度表的时间进行开发,感觉每天都是deadline。”

首先,编程工作的复杂性不可避免地会导致进度表的不确定性。程序员需要面对各种不同的技术难题和复杂的业务逻辑,每个问题都需要一定的时间来解决。同时,编程工作也可能会遇到方方面面的问题,如代码冲突、代码质量问题等等,这些问题都需要耗费时间去解决,导致进度表的不确定性。


其次,软件开发过程中的变化和风险也是导致进度表不断调整的原因之一。在软件开发过程中,往往会遇到需求变更、功能重构等情况,这些变化可能会对原有的进度表造成影响。此外,软件开发过程中也会存在各种风险,如技术实现难度、合作伙伴变更等,这些风险也会对项目进度表的稳定性造成影响。


综上所述,程序员项目进度表的不确定性是由编程工作的复杂性和软件开发过程中的变化和风险导致的。为避免影响项目进度和开发质量,程序员需要及时调整进度表,以确保项目能够按时交付,并保持项目质量的稳定性。


二、炫技代码分享

越是高级的程序员,越是在ctrl+c和ctrl+v上,运用的炉火纯青。

我个人基本认同但是又有点否认:因为不是你想ctrl+c和ctrl+v,就可以ctrl+c和ctrl+v的。


说程序员开发都是复制和粘贴纯属误解。虽然程序员在开发过程中经常会使用已经存在的代码(也就是所谓的复制和粘贴),但是这只是开发过程中的一个小部分。


实际上,程序员在开发过程中需要设计算法、编写代码和进行测试等多个阶段。设计算法需要程序员具备扎实的数学和计算机科学知识,能够理解并解决复杂的问题。编写代码需要程序员掌握编程语言和开发工具,能够将算法转化为实际的代码实现,同时还需要对代码的质量、可读性和维护性进行考虑。进行测试则需要程序员利用各种测试工具和技术,确保程序的正确性和稳定性。


虽然程序员会从互联网或其他代码库中寻找已有的代码来提高效率,但是这并不代表程序员只会复制和粘贴。在使用已有的代码时,程序员需要理解其逻辑和实现方法,并根据实际需求进行适当修改和优化,以满足个性化的需求。此外,复制粘贴的代码也需要经过测试和调试等多个步骤,以确保代码的正确性和稳定性。


总之,程序员的工作不仅包括复制和粘贴代码,更需要具备严密的思维、扎实的知识和高超的技术,才能够完成高质量的开发工作。


三、案例分享

5月中旬,小鹅通对接的第三方平台,提前上线。

  • 测试、代码调整,基本上是在不断修改的过程中进行的…
  • 甲方电话、微信等多种方式的轰炸,带来的压力…
  • 熬夜,就餐规律紊乱…

好吧,熬过来了。在DEADLINE,终于完成了小鹅通学习记录大批量队列同步,效果如下:


1.项目需求

单次报名人数超过3万人次,而小鹅通的token获取频次和学习记录更新频次都有限制,无法直接批量处理;

PHP脚本语言限制,无法多线程进行:即实现单击事件后在后台自动处理;

超级管理员在培训结束后,在课程完成后,一次性完成课程进度和学习时长;个人会员登录自己后台,单独更新自己的学习进度。

php有sleep函数,但是和python的执行区别很大,php总是在执行完全部进程才会在前端输出,这是php特性决定。如何让管理员实时知道同步记录呢?


javascript不是有setTimeout函数吗?分时分批执行应该可以解决这个需求。


2.开发实战

(1)引入外部js库

    <!--layui核心框架-->
    <script src="static/layui/layui.js"></script>
    <link rel="stylesheet" href="static/layui/css/layui.css" media="all">


(2)创建HTML容器

<div class="layui-fluid">
    <!--提示说明-->
    <div class="layui-card">
        <div class="layui-card-body">
            <div class="layui-card">
                <div class="layui-card-body" style="padding: 15px;text-align: center;">
                    <button class="layui-btn" id="sync"><i class="layui-icon layui-icon-time"></i> 队列同步</button>
                    <button class="layui-btn layui-btn-danger" id="cancelSync"><i
                            class="layui-icon layui-icon-logout"></i>停止同步
                    </button>
                </div>
            </div>
            <div class="layui-card">
                <div class="layui-card-header"><strong>提示说明:</strong></div>
                <div class="layui-card-body">
                    <div class="layui-form-item">
                        <p>1.基于小鹅通token和学习记录API接口的限制,采用队列同步大数据量;</p>
                        <p class="x-red">2.同步前,请先同步用户小鹅通user_eid;</p>
                        <p>3.为减少小鹅通接口的使用频率,建议课程结束后,进展同步;</p>
                        <p>4.同步时,不能关闭窗口,请最小化后进行其他事件操作;</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!--同步信息记录-->
    <div class="layui-card">
        <div class="layui-card-body">
            <div class="layui-card">
                <div class="layui-card-header"><strong><span class="x-red" id="total"></span></strong></div>
                <div class="layui-card-body">
                    <div class="layui-form-item" id="content"></div>
                </div>
            </div>
        </div>
    </div>
</div>


(3)队列同步延迟执行

 //同步队列
    $("#sync").click(function () {
        $.getJSON('./api/api.php?act=getStudyUser&token=3cab7ce4142608c0f40c785b5ab5ca24', {course_id: course_id}, function (res) {
            //console.log(res.data);
            if (res.data.length == 0) {
                $("#total").html("学习记录全部同步,无需重复操作。")
            } else {
                //禁止操作
                $("#sync").attr("disabled", true).addClass("layui-btn layui-btn-primary");
                //同步数据
                outputArrayInBatch(res.data, 0, 90);
            }
        })
    })
    //停止执行
    $("#cancelSync").click(function () {
        location.reload();
    })
    //封装函数;
    function outputArrayInBatch(arr, batchNum, interval) {
        var startIndex = batchNum * interval; // 当前批次的起始索引
        var endIndex = (batchNum + 1) * interval; // 当前批次的结束索引
        if (startIndex > arr.length - 1) {
            return;
        }
        if (endIndex > arr.length) {
            endIndex = arr.length;
        }
        var batchArr = arr.slice(startIndex, endIndex);
        //console.log(batchArr);
        //计算剩余数量
        var total = arr.length - startIndex;
        //当结余数量不足完整批次时,自动清零
        if (total <= interval) {
            total = 0;
        }
        $("#total").html("总数量:" + total + "条记录,预计批次:" + Math.ceil(total / interval) + ",预计执行时间:" + parseFloat(total * 1 / interval / 60).toFixed(2) + "分钟");
        $("#content").append("<p>第" + (batchNum + 1) + "批次,完成同步...<p>");
        //同步记录并入库
        $.ajax({
            type: "post",
            url: "./api/api.php?act=updateStudyRecord&token=3cab7ce4142608c0f40c785b5ab5ca24",
            async: true,
            data: {
                course_id: course_id,
                resource_id: resource_id,
                batch_user_list: batchArr
            },
            dataType: "json",
            success: function (res) {
                console.log(res);
                if (res.code.code == 2054) {
                    layer.msg('小鹅通API的请求短时间突增,稍等片刻重新同步', {icon: 2, timeout: 2000}, function () {
                        location.reload();
                    })
                    return false;
                }
            },
            error: function (err) {
                console.log(err);
            }
        });
        //延迟执行
        setTimeout(function () {
            outputArrayInBatch(arr, batchNum + 1, interval);
        }, 1000); // 每隔1秒输出一批次
    }


(4)获取大数据量数据

 public function getStudyUser()
    {
        checkAdminAuth($_COOKIE['admin_roles'], '0', 1);//超管权限
        global $db, $res;
        dbc();
        @$course_id = get_param('course_id');
        $sql = "select sign_id,user_eid FROM " . $db->table('sign_2023') . " WHERE sync_mark = 0 AND user_eid <> ''";
        $sql .= " AND course_id = " . $course_id;//必须指定课程ID
        $sql .= " ORDER BY sign_id ASC";//升序执行
        $row = $db->queryall($sql);
        $res["data"] = $row;
        die(json_encode_lockdata($res));
    }


(5)php批量更新

  • 获取有学习记录的,更新学习时长和学习进度;
  • 没有学习记录,直接更新是否更新过的标识,避免重复更新;
 //学习记录-同步至数据表
    public function updateStudyRecord()
    {
        checkAdminAuth($_COOKIE['admin_roles'], '0', 1);//超管权限
        global $db, $res;
        dbc();
        //1.获取参数
        @$course_id = $_POST['course_id'];
        @$resource_id = $_POST['resource_id'];
        @$batch_user_list = $_POST['batch_user_list'];
        /*2.同步获取小鹅通学习记录
         * $res['xiaoE']['code'] 状态码
         * $res['xiaoE']['data']['list'],返回小鹅通学习记录数组
         * $res['xiaoE']['data']['list'][0]['learn_progress'],学习进度
         * $res['xiaoE']['data']['list'][0]['stay_time'],学习时间,单位为秒
         * $res['xiaoE']['data']['list'][0]['user_id'],小鹅通user_id
        */
        $user_list = array();
        for ($i = 0; $i < count($batch_user_list); $i++) {
            $user_list[] = $batch_user_list[$i]['user_eid'];
        }
        require_once '../libs/Client.php';
        $client = new Client();
        $url = "https://api.xiaoe-tech.com/xe.user.leaning_record_by_resource.get/1.0.0";
        $method = "post";
        $data = array("search_max_learn_progress" => 0,
            "stay_time" => 0,
            "list" => $user_list);
        $params = ["resource_id" => $resource_id, 'data' => $data];
        $result = $client->request($method, $url, $params);
        $dataList = $result['data']['list'];
        //3.同步数据
        $xiaoData_user = array();
        if ($dataList) {
            $xiaoData = array();
            $len = count($dataList);
            for ($j = 0; $j < $len; $j++) {
                $xiaoData_user[] = $dataList[$j]['user_id'];
                $xiaoData[] = array('user_eid' => $dataList[$j]['user_id'], 'learn_progress' => $dataList[$j]['learn_progress'], 'stay_time' => $dataList[$j]['stay_time'], 'sync_mark' => 1);
            }
            //4-1.有学习记录-同步数据
            if (!empty($xiaoData)) {
                $sql = batchUpdate($db->table('sign_2023'), $xiaoData, "user_eid", ["course_id" => $course_id, "sync_mark" => 0]);
                $db->query($sql);
            }
        }
        //4.无学习记录的-更改状态码
        $noXiaoData = array();
        $diffXiaoData = array_diff($user_list, $xiaoData_user);
        for ($n = 0; $n < count($diffXiaoData); $n++) {
            $noXiaoData[$n]['user_eid'] = $diffXiaoData[$n];
            $noXiaoData[$n]['sync_mark'] = 1;
        }
        if (!empty($noXiaoData)) {
            $sql = batchUpdate($db->table('sign_2023'), $noXiaoData, "user_eid", ["course_id" => $course_id, "sync_mark" => 0]);
            $db->query($sql);
        }
        //输出状态
        $res['code'] = $result;
        $res["data"] = "课程同步学习记录,Status:OK";
        die(json_encode_lockdata($res));
    }


(6)小鹅云API实时关注状态

(7)前端控制台打印测试

四、如何学习高级技术

天下事有难易乎?为之则难者亦易矣;不为,则易者亦难矣。人之为学有难易乎?学之,则难者亦易矣;不学,则易者亦难矣。


  1. 掌握必要的基础知识:学习高级技术需要先掌握必要的基础知识,例如数学、计算机基础、编程语言、算法等。只有掌握了这些基础知识,才能更好地理解和学习高级技术。
  2. 阅读优秀的编程书籍:阅读编程书籍是学习高级技术的一个非常有效的方式。可以选择一些经典的编程书籍,并注重理解书中的概念和思想。
  3. 参与开源项目:参与开源项目可以学习到许多高级技术,同时也可以通过和其他开发者的交流和合作获得宝贵的经验。可以选择一些开源项目并贡献自己的代码和想法。
  4. 参加高级培训课程:参加高级培训课程是学习高级技术的一个重要途径,可以选择一些著名的在线课程平台或线下培训机构进行学习。在培训过程中,可以获得更专业的指导和学习材料。
  5. 自己动手实践:学习高级技术需要不断地进行实践和运用。可以选择一些适合自己水平的项目进行开发和实践,比如仿写已有软件或自主设计项目,从中获得经验和提高技术能力。
  6. 总之,学习高级技术需要坚持不懈地进行学习和实践,同时注重深入理解和思考,从而掌握更高级的技术能力。


@漏刻有时

相关文章
|
6月前
|
Java 云计算
Java多线程编程中的同步与互斥机制探析
在当今软件开发领域,多线程编程是一项至关重要的技能。本文将深入探讨Java中的同步与互斥机制,分析其在多线程环境下的应用及实现原理,帮助读者更好地理解并运用这一关键技术。
71 4
|
6月前
同步模式之顺序控制(笔试)
同步模式之顺序控制(笔试)
30 0
|
存储 安全 Java
到底如何保证线程安全,总结得太好了。。
一、线程安全等级 之前的博客中已有所提及“线程安全”问题,一般我们常说某某类是线程安全的,某某是非线程安全的。其实线程安全并不是一个“非黑即白”单项选择题。
976 0
到底如何保证线程安全,总结得太好了。。
|
3月前
|
消息中间件 Java Kafka
Kafka不重复消费的终极秘籍!解锁幂等性、偏移量、去重神器,让你的数据流稳如老狗,告别数据混乱时代!
【8月更文挑战第24天】Apache Kafka作为一款领先的分布式流处理平台,凭借其卓越的高吞吐量与低延迟特性,在大数据处理领域中占据重要地位。然而,在利用Kafka进行数据处理时,如何有效避免重复消费成为众多开发者关注的焦点。本文深入探讨了Kafka中可能出现重复消费的原因,并提出了四种实用的解决方案:利用消息偏移量手动控制消费进度;启用幂等性生产者确保消息不被重复发送;在消费者端实施去重机制;以及借助Kafka的事务支持实现精确的一次性处理。通过这些方法,开发者可根据不同的应用场景灵活选择最适合的策略,从而保障数据处理的准确性和一致性。
204 9
|
3月前
|
消息中间件 存储 Kafka
【Kafka大揭秘】掌握这些秘籍,让你的消息状态跟踪稳如老狗,再也不怕数据丢失的尴尬时刻!
【8月更文挑战第24天】Kafka作为一个领先的分布式流数据平台,凭借其出色的性能和扩展性广受青睐。为了保障消息的可靠传输与处理,Kafka提供了一系列核心机制:生产者确认确保消息成功到达;消费者位移管理支持消息追踪与恢复;事务性消息保证数据一致性;Kafka Streams的状态存储则适用于复杂的流处理任务。本文将详细解析这些机制并附带示例代码,帮助开发者构建高效稳定的消息处理系统。
39 5
|
3月前
|
缓存 算法 网络性能优化
解决网络延迟和阻塞,有它,不服都不行!
解决网络延迟和阻塞,有它,不服都不行!
|
11月前
|
前端开发 Cloud Native 大数据
坑爹,线上同步近 3w 个用户导致链路阻塞引入发的线上问题,你经历过吗?
坑爹,线上同步近 3w 个用户导致链路阻塞引入发的线上问题,你经历过吗?
【软考学习9】进程的同步与互斥、生产消费者模型
【软考学习9】进程的同步与互斥、生产消费者模型
193 0
|
设计模式 NoSQL Redis
Bio多线程消费者模式撑起Redis后台任务的半壁江上,这篇我干了,大家随意!
Bio多线程消费者模式撑起Redis后台任务的半壁江上,这篇我干了,大家随意!