当前位置: 首页 > news >正文

自助建网站哪个好/爱站网收录

自助建网站哪个好,爱站网收录,湖北日报官方网站,网站的优化和推广方案怎么写前言 直播间贡献榜是一种常见的直播平台功能,用于展示观众在直播过程中的贡献情况。它可以根据观众的互动行为和贡献值进行排名,并实时更新,以鼓励观众积极参与直播活动。 在直播间贡献榜中,每个观众都有一个对应的贡献值&#…

前言

直播间贡献榜是一种常见的直播平台功能,用于展示观众在直播过程中的贡献情况。它可以根据观众的互动行为和贡献值进行排名,并实时更新,以鼓励观众积极参与直播活动。

在直播间贡献榜中,每个观众都有一个对应的贡献值,贡献值用来衡量观众在直播过程中的贡献程度。观众的贡献值可以通过多种途径获得,比如送礼物、打赏主播等。

首先,我们需要创建一个贡献榜单,可以使用Redis的有序集合 (Sorted Set)结构来实现。在有序集合中,每个观众对应一个唯一的ID作为成员,而成员的分数表示观众的贡献值。可以根据观众每次送出礼物增加相应的贡献值。

当有新的观众参与直播并进行互动时,我们可以使用ZADD命令将其用户ID添加到贡献榜单中,并更新相应的贡献值。可以根据贡献值对观众进行排序,从而得到当前排名靠前的观众。

要实时更新贡献榜单,可以使用ZINCRBY命令增加观众的贡献值。当观众进行互动行为时,我们可以调用ZINCRBY命令增加相应观众的贡献值,并确保贡献榜单及时反映观众的最新贡献情况。

Redis实现命令

用户ID为Test1000的得到价值为1314的礼物时,以及获取排行榜时,命令如下。比如

# 增加排行榜用户数据ZINCRBY ROUND_LIST_CACHE_20221222 1314 Test1000# 展示用户榜单ZRANGE ROUND_LIST_CACHE_20221222 0 -1 WITHSCORES

JAVA简单逻辑代码实现 

1.Spring boot的yml配置文件,配置礼物队列

       
#yml配置文件配置队列 
GiftFlowOutput: content-type: application/jsondestination: gift_all_flow
GiftFlowInput: #礼物队列content-type: application/jsongroup: GiftAllFlowGroup

2.redis使用lua脚本增加榜单,保证多机并发原子性

//redis lua脚本配置
@Slf4j
@Configuration
public class RedisConfig {@Autowiredprivate JdkCacheHandler jdkCacheHandler;@Bean("zsetScoreScript")public RedisScript<Long> zsetScoreScript() {DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("/lua/zadd.lua")));redisScript.setResultType(Long.class);return redisScript;}
}

3。LUA脚本具体实现,保留3位有效礼物小数位,后面小数位用于同个时间刷礼物进行排序,目前这里只精确到了秒

local key=KEYS[1]
local member=KEYS[2]
local newValue=tonumber(string.format("%.16f",ARGV[1]))
local oldValue=redis.call('ZSCORE',key,member)
if type(oldValue) == 'boolean' thenredis.call('ZADD',key,newValue,member)return 1
elseredis.call('ZADD',key,tonumber(string.format("%.3f",oldValue))+newValue,member)return 1
end
return 0

 4.调用lua脚本,增加排行榜积分

@Component
@Slf4j
public class RankScoreUtilManager {private final static DecimalFormat format = new DecimalFormat(ActivityBase.TOTAL_FORMAT);@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate ActivityTimeCache activityTimeCache;@Resource(name = "zsetScoreScript")private RedisScript<Long> zaddScript;/*** 添加分数到排行榜,可以并发的*/public void addScoreToRank(String cacheKey, String anchorId, BigDecimal integral, Date eventTime) {try {BigDecimal bigDecimal = dealScore(integral, activityTimeCache.getActivityDTO().getEndTime(), eventTime);String score = format.format(bigDecimal.doubleValue());Long execute = redisTemplate.execute(zaddScript, Arrays.asList(cacheKey, anchorId), score);log.warn("增加积分到排行榜integral={},anchorId={},score={},execute",integral,anchorId,score,execute);} catch (Exception e) {log.error("增加异常", e);}}private static BigDecimal dealScore(BigDecimal newScore, LocalDateTime activityEndTime, Date eventDate) {DecimalFormat format = new DecimalFormat(ActivityBase.VALID_FORMAT);String formatStr = format.format(EeBigDecimalUtil.scale(newScore, ActivityBase.VALID_SCALE, RoundingMode.DOWN).doubleValue());StringBuilder sb = new StringBuilder(32);//后面补个0,避免lua进1出错sb.append(formatStr).append('0');long n = EeDateUtil.getMilli(activityEndTime) - eventDate.getTime();String s = Long.toString(Math.abs(n) / 1000);for (int i = s.length(); i < ActivityBase.TIME_SCALE; i++) {sb.append('0');}sb.append(s);return new BigDecimal(sb.toString()).setScale(ActivityBase.TOTAL_SCALE, RoundingMode.DOWN);}}

5.配置礼物队列名称 

/**
* 监听礼物流水队列
*/
public interface AllGiftFlowProcessor {String OUTPUT = "GiftFlowOutput";@Output(OUTPUT)MessageChannel output();String INPUT = "GiftFlowInput";@Input(INPUT)SubscribableChannel input();
}

 6.监听礼物队列的listener,前面做了一些活动时间校验的判断,最关键的是最下面roundListBusiness.dealAnchorRoundList(dto);的方法


//监听礼物队列,处理相关业务逻辑,榜单的处理在最下面@Slf4j
@Service
public class AllGiftFlowListener {@Autowiredprivate RedisTemplate<String, String> redisTemplate;@Autowiredprivate AnchorLevelBusiness anchorLevelBusiness;private static final String cacheKey = "GIFT:TASK:INTER:EVENT:";@Autowiredprivate EeEnvironmentHolder eeEnvironmentHolder;@Autowiredprivate ActivityRoundDao activityRoundDao;@Autowiredprivate ActivityTimeCache activityTimeCache;@Autowiredprivate GiftConfigCache giftConfigCache;@Autowiredprivate GiftFlowProcessor giftFlowProcessor;@Autowiredprivate AnchorCache anchorCache;@Autowiredprivate RoundListBusiness roundListBusiness;@Autowiredprivate EeLog eeLog;@StreamListener(AllGiftFlowProcessor.INPUT)public void onReceive(ActivityGiftEventDTO dto) {MqConsumeRunner.run(dto.getEventId().toString(), dto, o -> dealMsgEvent(o), "TaskIntegralProcessor [{}]", dto);}private void dealMsgEvent(ActivityGiftEventDTO dto) {// 过滤非活动时间礼物ActivityDTO activityDTO = activityTimeCache.getActivityDTO();if (null == activityDTO) {return;}if (EeDateUtil.toLocalDateTime(dto.getEventDate()).isBefore(activityDTO.getStartTime())) {eeLog.info("礼物时间小于活动开始时间,丢弃礼物");return;}// 判断活动时间if (ActivityStatusEnum.NO_START == activityRoundDao.getActivityStatus()) {return;}// 过滤活动礼物if (giftConfigCache.getData().stream().noneMatch(o -> o.getGiftId().equals(dto.getGiftId()))) {eeLog.info("礼物id:{}不计算", dto.getGiftId());return;}Integer region = anchorCache.getRegionById(dto.getTarget());// 是否为签区域主播if (null == region || !ActivityBase.AnchorRegion.contains(region)) {eeLog.warn("该主播非签约或非参赛区域:{}", dto.getTarget());return;}// 是否重复消费礼物Boolean success = redisTemplate.opsForValue().setIfAbsent(cacheKey + dto.getEventId(), "", 15, TimeUnit.DAYS);if (success != null && !success) {eeLog.info("升级事件已处理:" + dto);return;}try {//监听礼物并且处理榜单(最主要的代码就这一句)roundListBusiness.dealAnchorRoundList(dto);} catch (Exception e) {log.error("处理榜单 fail.[" + dto + "]", e);}}}

 7.榜单的具体实现逻辑

@Component
@Slf4j
public class RoundListBusiness {//平台主播榜单private final static String CHRISTMAS_ROUND_ANCHOR_LIST = "CHRISTMAS:ROUND:ANCHOR:LIST";private final static String CHRISTMAS_ROUND_LIST_LOCK = "CHRISTMAS:ROUND:LIST:LOCK";@Autowiredprivate RankScoreUtilManager rankScoreUtilManager;@Autowiredprivate ActivityTimeCache activityTimeCache;@AutowiredRedisTemplate<String, String> redisTemplate;@Autowiredprivate AllGiftFlowProcessor allGiftFlowProcessor;/*** 处理榜单加分逻辑*/public void dealAnchorRoundList(ActivityGiftEventDTO dto) {ActivityDTO activityDTO = activityTimeCache.getActivityDTO();if (EeDateUtil.toLocalDateTime(dto.getEventDate()).isBefore(activityDTO.getStartTime())) {return;}if (!EeDateUtil.toLocalDateTime(dto.getEventDate()).isBefore(activityDTO.getEndTime())) {return;}//记录总的榜单流水try {//插入总的流水allGiftFlowProcessor.output().send(MessageBuilder.withPayload(dto).build());} catch (Exception e) {log.error("插入总的礼物流水异常dto={}", dto, e);}LocalDateTime now = LocalDateTime.now();if (!now.isBefore(activityDTO.getEndTime())) {//2.判断是否符合处理上一轮榜单的逻辑if (isThrowAwayBeforeGift(dto.getEventId(), now, activityDTO.getEndTime())) {log.warn("这里跳出了dto={},now={}", dto, EeDateUtil.format(now));return;}}dealRoundList(dto, dto.getTotalStarAmount());}/*** 处理主播榜单加分逻辑*/private void dealRoundList(ActivityGiftEventDTO dto, BigDecimal value) {//增加平台主播榜单incrAnchorListValue(CHRISTMAS_ROUND_ANCHOR_LIST, dto.getTarget(), value, dto.getEventDate());}/*** 具体加分方法*/public void incrAnchorListValue(String listCacheKey, String userId, BigDecimal value, Date eventTime) {if (EeStringUtil.isNotEmpty(listCacheKey)) {//增加榜单分数rankScoreUtilManager.addScoreToRank(listCacheKey, userId, value, eventTime);}}/*** 判断是否已经超过结算时间*/private boolean isThrowAwayBeforeGift(String eventId, LocalDateTime now, LocalDateTime endTime) {//如果当前时间超过了结算时间,直接丢弃礼物if (!now.isBefore(endTime.plusSeconds(ActivityBase.PROCESS_TS))) {log.error("主播榜单-当前时间超过了结算时间,直接丢弃礼物: {}", eventId);return true;}//如果上一轮的榜单已经锁定,丢弃礼物if (checkBlockRankList(CHRISTMAS_ROUND_ANCHOR_LIST)) {log.error("主播榜单-榜单被锁定后丢弃礼物: {}, {}", eventId, EeDateUtil.format(LocalDateTime.now()));return true;}return false;}/*** 判断结算时榜单是否已经被锁定*/public boolean checkBlockRankList(String listCacheKey) {Boolean cache = redisTemplate.opsForHash().hasKey(CHRISTMAS_ROUND_LIST_LOCK, listCacheKey);return null != cache && cache;}/*** 锁定榜单,把锁定的榜单都放入一个hash中*/public void setBlockRankList(String cacheKey) {redisTemplate.opsForHash().put(CHRISTMAS_ROUND_LIST_LOCK, cacheKey, EeDateUtil.format(LocalDateTime.now()));}
}

总结:目前这段代码只是实现了简单的日榜逻辑,还有一段结算的代码我没有复制出来,结算榜单无非就是在每天0点的时候结算前一天的榜单,对榜单前几名的主播进行礼物发放,后续将会更新几种复杂榜单的实现方式,包括:晋级榜单,积分晋级榜单,滚动日榜,滚动周榜,滚动月榜的一些实现方式

相关文章:

Redis实现日榜|直播间榜单|排行榜|Redis实现日榜01

前言 直播间贡献榜是一种常见的直播平台功能&#xff0c;用于展示观众在直播过程中的贡献情况。它可以根据观众的互动行为和贡献值进行排名&#xff0c;并实时更新&#xff0c;以鼓励观众积极参与直播活动。 在直播间贡献榜中&#xff0c;每个观众都有一个对应的贡献值&#…...

如何使用内网穿透工具实现Java远程连接本地Elasticsearch搜索分析引擎

文章目录 前言1. Windows 安装 Cpolar2. 创建Elasticsearch公网连接地址3. 远程连接Elasticsearch4. 设置固定二级子域名 前言 简单几步,结合Cpolar 内网穿透工具实现Java 远程连接操作本地分布式搜索和数据分析引擎Elasticsearch。 Cpolar内网穿透提供了更高的安全性和隐私保…...

C语言数据结构-----常用七种排序介绍、分类、实现及性能比较

前言 ①排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 ②稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&#…...

2023年山东省职业院校技能大赛高职组 “软件测试”赛项竞赛任务四 单元测试

任务四 单元测试 任务要求 题目1&#xff1a;任意输入2个正整数值分别存入x、y中&#xff0c;据此完成下述分析&#xff1a;若x≤0或y≤0&#xff0c;则提示&#xff1a;“输入不符合要求。”&#xff1b;若2值相同&#xff0c;则提示“可以构建圆形或正方形”&#xff1b;若2…...

在Redis客户端设置连接密码 并演示密码登录

我们先连接到Redis服务 然后 我们要输入 CONFIG SET requirepass “新密码” 例如 CONFIG SET requirepass "A15167"这样 密码就被设置成立 A15167 我们 输入 AUTH 密码 例如 AUTH A15167这里 返回OK说明成功了 然后 我们退出在登录就真的需要 redis-cli -h IP地…...

阿里云公有云平台

1. 请简要介绍一下公有云平台的基本概念和特点。 公有云是一种云计算模型&#xff0c;其中服务器、网络和存储资源等IT基础架构以虚拟资源的形式提供&#xff0c;并且可以通过互联网进行访问。这些资源是由第三方提供商共享并提供给用户的&#xff0c;包括计算、存储、网络等。…...

Zookeeper的学习笔记

Zookeeper概念 Zookeeper是一个树形目录服务&#xff0c;简称zk。 Zookeeper是一个分布式的、开源的分布式应用程序的协调服务 Zookeeper提供主要的功能包括&#xff1a;配置管理&#xff0c;分布式锁&#xff0c;集群管理 Zookeeper命令操作 zk数据模型 zk中的每一个节点…...

leetcode2两数加和问题(链表)

题目思路&#xff1a; ①创建一个int类型的局部变量&#xff0c;用来存储两个结点的Val值。 ②判断该Val值与10求余(mod)后是否大于0,如果大于0, 则需要在下一个结点进位。 ③最关键的步骤&#xff1a;实现l1&#xff0c;l2结点数值相加后构建新的存储求和后的结点&#xff0…...

VSCode中配置prettier和ESLint

文章目录 了解ESLint和Prettier的作用prettier配置ESLint配置常见问答ESLint 和Prettier 有什么区别&#xff1f;为什么我应该同时使用ESLint 和Prettier&#xff1f;在使用ESLint 和Prettier 时&#xff0c;有可能出现它们之间的规则冲突吗&#xff1f;我已经在项目中使用了ES…...

如何将本地websocket发布至公网并实现远程访问服务端

文章目录 1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功,暴露端口默认99995. 创建隧道映射内网端口6. 查看状态->在线隧道,复制所创建隧道的公网地址加端口号7. 以…...

分享 | 软件测试的基本流程是什么?软件测试流程详细介绍

软件测试 软件测试和软件开发一样&#xff0c;是一个比较复杂的工作过程&#xff0c;如果无章法可循&#xff0c;随意进行测试势必会造成测试工作的混乱。为了使测试工作标准化、规范化&#xff0c;并且快速、高效、高质量地完成测试工作&#xff0c;需要制订完整且具体的测试…...

浮点数的转换--IEEE 754

IEEE754标准是一种浮点数表示标准&#xff0c;一般分为 单精度&#xff08;32位的二进制数&#xff09;&#xff1b;双精度&#xff08;64位的二进制数&#xff09; 根据国际标准IEEE754&#xff0c;任意一个二进制浮点数V可以表示为下面形式&#xff1a; V (-1)^s *&#…...

若依框架介绍

RuoYi&#xff08;若依&#xff09;是一款基于Spring Boot、Spring Cloud等开源框架搭建的企业级开发平台&#xff0c;旨在提供全面的解决方案&#xff0c;简化企业级应用开发&#xff0c;提高开发效率。 主要特点&#xff1a; 1. 模块化设计 RuoYi采用模块化的设计&#xff0…...

iMazing2024免费版iOS移动设备管理软件

以自己的方式管理iPhone&#xff0c;让备受信赖的软件为您传输和保存音乐、消息、文件和数据。安全备份任何 iPhone、iPad 或 iPod touch。iMazing 功能强大、易于使用&#xff0c;称得上是 Mac 和 PC 上最好的 iOS 设备管理器。 正在为iTunes繁琐的操作发愁&#xff1f;设备数…...

Zookeeper整合Java实战,不同客户端使用汇总

Java学习面试指南&#xff1a;https://javaxiaobear.cn ZooKeeper应用的开发主要通过Java客户端API去连接和操作ZooKeeper集群。可供选择的Java客户端API有&#xff1a; ZooKeeper官方的Java客户端API。 第三方的Java客户端API&#xff0c;比如Curator。 ZooKeeper官方的客户…...

【python】Ubuntu下安装spyder及matplotlib中文显示

一、查看Ubuntu版本 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.3 LTS Release: 22.04 Codename: jammy尝试用cat /etc/debian_version命令&#xff0c;竟然可以显示出来Debian的版本。 $ cat /etc/debian_version …...

Vue中操作dom,jQuery添加css类,document对象不可使用

...

《运维人员的未来:IT界的“万金油“如何继续闪耀光芒》

文章目录 每日一句正能量前言35岁被称为运维半衰期&#xff0c;究竟为何&#xff1f;如何顺利过渡半衰期运维的职业发展路径后记 每日一句正能量 凡事顺其自然&#xff0c;遇事处于泰然&#xff0c;得意之时淡然&#xff0c;失意之时坦然&#xff0c;艰辛曲折必然&#xff0c;历…...

ip addr和ifconfig

ip addr可以显示更多信息&#xff0c;包括为启动的网络驱动如wlan&#xff0c;而ifocnfig只显示在线的驱动。若wlan是down的&#xff0c;则ip addr会显示信息&#xff0c;ifconfig不会显示信息。 ip addr: ifconfig:...

Crow:Middlewares 庖丁解牛7 after_handlers_call_helper

Crow:Middlewares 庖丁解牛6 middleware_call_helper-CSDN博客 介绍了对插件before_handle的调用 当完成了detail::middleware_call_helper的调用后,如果没有在before_handle中设置req被终止处理,也就是 if (!res.completed_) {need_to_call_after_handlers_ = true;handler…...

ts相关笔记(extends、infer、Pick、Omit)

最近刷了本ts小册&#xff0c;对一些知识点做下笔记。 extends extends 是一个关键字&#xff0c;用于对类型参数做一些约束。 A extends B 意味着 A 是 B 的子类型&#xff0c;比如下面是成立的 ‘abc’ extends string599 extends number 看下面例子&#xff1a; type …...

8.21 PowerBI系列之DAX函数专题-帕累托分析

需求 实现 1 按商品小类累积 var rollup_sales calculate(//计算当前累计销售额 [销售额], filter(allselected(order_2[产品小类]),sum(order_2[订单金额])<[销售额]) ) //按小类累积金额,filter内的销售额为选中的各小类的销售额 //金额从大到小累积&#xff0c;用&l…...

结构体-2-测试排名

22-结构体-2-测试排名 [命题人 : 外部导入] 时间限制 : 1.000 sec 内存限制 : 128 MB 题目描述 为了提升同学们的编程能力&#xff0c;老师们会在平时进行C语言的上机测试&#xff0c;了解班上同学的学习情况&#xff0c;对于一些测试成绩较差的同学&#xff0c;老师会进行督促…...

LeetCode刷题---快乐数

解题思路 该题的解题思路为使用哈希表来存储每次平方的和的结果&#xff0c;看是否有重复的数&#xff0c;如果存在第n次的平方和的数和第i次(i<n)平方和的数想等&#xff0c;那么它就不是一个快乐数。否则&#xff0c;则为快乐数。 代码实现&#xff1a; public boolean i…...

web前端游戏项目-辨色大比拼【附源码】

web前端游戏项目-辨色大比拼【附源码】 《辨色大比拼》是一个旨在测试和提升玩家颜色识别能力的在线游戏。在游戏中&#xff0c;玩家将通过辨识颜色来解谜并推进游戏进程。辨色大比拼也是一个寓教于乐的游戏&#xff0c;它不仅提供了一个有趣的辨色挑战&#xff0c;还能帮助玩…...

MongoDB操作_数据库_集合

.......................................................................................................................................................... 三、MongoDB操作 3.1 数据库操作 一个mongodb中可以建立多个数据库。 MongoDB的默认数据库为"test…...

50个免费的 AI 工具,提升工作效率(附网址)

上次我们已经介绍了20个精选的提高工作效率的免费AI工具&#xff0c;但如果你觉得这些AI工具还不过瘾的话&#xff0c;想进一步成为职场中最了解AI的人&#xff0c;本文将汇总介绍免费最新的50个AI工具。 DeepSwap DeepSwap 是一个基于 AI 的工具&#xff0c;适用于想要制作令人…...

g++ strip debug

strip(1) command_--strip-debug-CSDN博客 strip main.outll main.out -rwxr-xr-x 1 root root 6272 Mar 22 16:14 main.outfile main.out main.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, Bu…...

微服务实战系列之Dubbo(上)

前言 随着一年一度冬至的到来&#xff0c;2023的步伐也将远去。而博主的系列文章&#xff0c;也将从今天起&#xff0c;越来越聚焦如何构建微服务“内核”上。前序系列文章几乎囊括了微服务的方方面面&#xff0c;无论使用什么框架、组件或工具&#xff0c;皆可拿来用之。 那么…...

一篇讲透:箭头函数、普通函数有什么区别

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热衷分享有趣实用的文章&#xff0c;希望大家多多支持&#xff0c;一起进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 目录 什么是箭头函数 箭头函数和普通函数的区别 更简洁的语法 箭头函数…...