有一个需求是客户端需要后端推送所有学生是否在线列表,大致数据类型长这样:
[{studentID: 216775, online: 1},{studentID: 21275, online: 1},{studentID: 11625, online: 0}]
项目原先的设计是将所有学生信息一次性推送下去,但是这样的设计,待学生越来越多的时候,消息量就会变得巨大,网络I/O的消耗就会很大,为了减少网络费用,提出了增量更新的设计,即当学生上线、下线的时候,服务端推送该学生在线状态变化,数据格式如:
{studentID:216674, online: 1}
可以极大的减少网络消息量,但是这样增量更新,无法保证两端数据的一致性,可能某一次推送可能失败了,这就会导致客户端没有接收到学生上线或者下线,从而导致两端数据不一致,为了保证两端数据一致性,我们提出了以下设计:
1、增量更新时,增加一个根据所有学生ID和学生在线状态组合起来的一个crc32校验码(全称是循环冗余校验,是最著名的数据一致性检错手段)。
具体方式:
服务端根据每个学生ID和在线状态(1或0)生成十六进制数,再用crc32进行处理,得到一串有符号的数字总和,即为校验码,服务端增量更新接口增加这个校验码,
2、客户端也会根据当前客户端存储的学生信息通过一样的方式得到校验码,然后与服务端下发的校验码进行对比,若不一致则表示两端数据不一样,
那么客户端就会请求获取当前所有在线学生列表,更新客户端的数据,从而保证了两端数据的一致性。
下面是nodejs版本的crc32校验码生成实现:
var CRC32 = require('crc-32'); // var studentList = [ // { amsID: "235556558", online: 0 }, // { amsID: "213888499", online: 1 }, // { amsID: "235556995", online: 1 }, // { amsID: "259999777", online: 0 } // ] var studentList = [ { amsID: "235556558", online: 0 }, { amsID: "213888499", online: 1 }, { amsID: "235556995", online: 1 }, { amsID: "259999777", online: 0 } ] var validateCode = 0; studentList.forEach(student => { studentCode = CRC32.buf(Buffer(student.amsID + student.online)); console.log(studentCode); validateCode += studentCode; }); console.log("validateCode == ", validateCode);
下面是java版本的crc32校验码生成实现:
package com.openmind.jwt; import java.util.zip.CRC32; /** * Created by Administrator on 2021/1/19. */ public class Valid { static String[] strIdArr = {"235556558","213888499","235556995","259999777"}; static String[] strStatusArr = {"0","1","1","0"}; /*public static int HashThreeDes(String[] strIdArr, String[] strStatusArr){ int valCode = 0; for (int i=0; i<strIdArr.length;i++){ System.out.println("id" + i +" hashcode:"+ strIdArr[i].hashCode() + ",status" + i +" hashcode:"+ strStatusArr[i].hashCode()); valCode = valCode + ThreeDesUtil.encrypt(strIdArr[i] + strStatusArr[i]).hashCode(); } return valCode; }*/ public static long HashCRC32(String[] strIdArr, String[] strStatusArr){ long valCode = 0; CRC32 crc = new CRC32(); for (int i=0; i<strIdArr.length;i++){ System.out.println("id" + i +" hashcode:"+ strIdArr[i].hashCode() + ",status" + i +" hashcode:"+ strStatusArr[i].hashCode()); crc.update((strIdArr[i]+strStatusArr[i]).getBytes()); valCode = valCode + crc.getValue(); } return valCode; } public static void main(String[] args) { //System.out.println("HashThreeDes valCode:" + HashThreeDes(strIdArr, strStatusArr)); System.out.println("HashCRC32 valCode:" + HashCRC32(strIdArr, strStatusArr)); } }