首页 文章 精选 留言 我的

精选列表

搜索[鸿蒙开发],共10000篇文章
优秀的个人博客,低调大师

每日一博 | BBBUG 音乐聊天室的开发故事和架构设计

办公室有个小伙伴喜欢拿音响放歌,然而总放一些动次打次的广场舞DJ曲目,同事听了都头大,每次让人家切歌又不方便 于是某同事吐槽:“我们点啥你放啥?” 一天之后…… “张三你刚说放啥来着?” “卧槽,我说的是刘德华的17岁,你这放的是谁的版本?” “17岁QQ音乐要会员,放不了。” …… 我实在看不下去了,要不写一个点歌平台? 说干就干,第一版俩小时搞定: 一个点歌端,爬虫爬各大平台,包括一些VIP歌曲也给爬下来,只能搜索,点歌。 一个导播端,可以看大伙点了什么歌,导播端可以插队播放,删除。 好,上线。 两天后…… 老板:“卧槽你们当办公室KTV呢?开音响听歌???” 好吧,所有人默默带上了耳机,但点歌端不能播放音乐,只能点歌,这一版宣告凉凉。 …… 那就升级吧: 这一版,不区分点歌端和导播端,所有端都一样,做一个共享队列,大伙点,大伙自己带耳机听。 一天后…… “你能不能让大家听到的歌进度保持一致?我还在听上一首,他们先进去的都已经自动播下一首了……” OK,继续升级,加歌曲同步。 好家伙这一次,跟KTV没啥区别了。 这一版有点意思,还加上了“送啤酒”这个小互动,是不是更像KTV了? 好吧我承认,这种小互动貌似没什么用,于是后来的版本掐掉了。 然而好景不长: “大厅这群人有毒吧?跟五条人杠上了?” “我实在是不敢恭维在座各位的歌单” “这都点的什么玩意歌啊……” “Mojito我实在是听得要吐了……” 好吧,那就安排,自己开房间听歌。 于是有了多房间的版本,每个人都可以创建自己的房间,听自己的歌。 顺便加上一个二级域名和独立域名的绑定功能,于是有了下面的设计图: 这就很棒了,大伙都可以在大厅一起听,也可以去自己房间里点歌听。 好好好景不长,需求又来了~ “自己的房间,能不能不点歌,自动播放自己点过的歌?” 安安安排! 那就来一个电台模式吧,设置了就自动播放自己的歌,有人点歌的话让他排队吧。 这下可以了吧? 安安稳稳听歌一周后…… “好无聊啊,光听歌,能让我听听相声小品吗?” 安安安安安排! 爬谁呢,就蜻蜓FM吧。 上线了小说故事模式…… 好好好好好景还是不长 “这个UI好丑啊,能换换吗?” 我也这么觉得,那就改吧,于是改成了这样 “白色是不是太晃了,出个暗黑模式呗?” “我TM……” 安安安安安安安排! 感觉还挺棒, 本以为故事到这里就基本结束了,然而,嗯。 “网页好烦人啊,能出个Windows客户端吗?” 安安安安安P,等下,C#我快忘干净了。 花俩小时回忆了下C#,又花俩小时学习了下 WTF…… 安安安安安安安排! 于是有了这个Windows客户端 好家伙,写完了,发布了,实际统计了下使用数据,使用人数不超过3,WTF???? “你这大部分是程序员在用,要不出个vscode的插件呗。” 我…… 故事快结束了吗? 天真。 “出个APP吧!” 我…… 好,安排,就拿Uniapp整一套吧。 体验还挺不错,不过因为音乐版权问题,这里就没上架AppStore。 “App下载好麻烦,整一套小程序吧?” 安安安安安安安安安安安安排! 整! 故事到这里就基本结束了,心累。 一口气把所有端的代码都开源了,欢迎有兴趣的小伙子给点点小星星呀。 Github https://github.com/HammCn Gitee https://gitee.com/bbbug_com 顺便附上整体的架构设计图 体验一下 https://www.bbbug.com

优秀的个人博客,低调大师

redis分布式锁的这些坑,我怀疑你是假的开发

摘要:用锁遇到过哪些问题? 一、白话分布式 什么是分布式,用最简单的话来说,就是为了较低单个服务器的压力,将功能分布在不同的机器上面;就比如: 本来一个程序员可以完成一个项目:需求->设计->编码->测试 但是项目多的时候,一个人也扛不住,这就需要不同的人进行分工合作了 这就是一个简单的分布式协同工作了; 二、分布式锁 首先看一个问题,如果说某个环节被终止或者别侵占,就会发生不可知的事情 这就会出现,设计好的或者设计的半成品会被破坏,导致后面环节出错; 这时候,我们就需要引入分布式锁的概念; 何为分布式锁? 当在分布式模型下,数据只有一份(或有限制),此时需要利用锁的技术控制某一时刻修改数据的进程数。 用一个状态值表示锁,对锁的占用和释放通过状态值来标识。 分布式锁的条件: 可以保证在分布式部署的应用集群中,同一个方法在同一时间只能被一台机器上的一个线程执行。 这把锁要是一把可重入锁(避免死锁) 这把锁最好是一把阻塞锁 这把锁最好是一把公平锁 有高可用的获取锁和释放锁功能 获取锁和释放锁的性能要好 分布式锁的实现: 分布式锁的实现由很多种,文件锁、数据库、redis等等,比较多,在实践中,还是redis做分布式锁性能会高一些; 三、redis实现分布式锁 首先看两个命令: setnx:将 key 的值设为 value,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。 SETNX 是SET if Not eXists的简写。 127.0.0.1:6379> set lock "unlock" OK 127.0.0.1:6379> setnx lock "unlock" (integer) 0 127.0.0.1:6379> setnx lock "lock" (integer) 0 127.0.0.1:6379> expire:EXPIRE key seconds 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除 127.0.0.1:6379> expire lock 10 (integer) 1 127.0.0.1:6379> ttl lock 8 127.0.0.1:6379> get lock (nil) 基于分布式锁的流程: 这就是一个简单的分布式锁的实现流程,具体代码实现也很简单,就不赘述了; 四、redis实现分布式锁问题 如果出现了这么一个问题:如果setnx是成功的,但是expire设置失败,那么后面如果出现了释放锁失败的问题,那么这个锁永远也不会被得到,业务将被锁死? 解决的办法:使用set的命令,同时设置锁和过期时间 set参数: set key value [EX seconds] [PX milliseconds] [NX|XX] EX seconds:设置失效时长,单位秒 PX milliseconds:设置失效时长,单位毫秒 NX:key不存在时设置value,成功返回OK,失败返回(nil) XX:key存在时设置value,成功返回OK,失败返回(nil) 实践: 127.0.0.1:6379> set unlock "234" EX 100 NX (nil) 127.0.0.1:6379> 127.0.0.1:6379> set test "111" EX 100 NX OK 这样就完美的解决了分布式锁的原子性。 五、用锁遇到过哪些问题?又是如何解决的? 未关闭资源 由于当前线程 获取到redis 锁,处理完业务后未及时释放锁,导致其它线程会一直尝试获取锁阻塞,例如:用Jedis客户端会报如下的错误信息 1redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool redis线程池已经没有空闲线程来处理客户端命令。使用原生方法记得关闭! 解决的方法也很简单,只要我们细心一点,拿到锁的线程处理完业务及时释放锁 B的锁被A给释放了 我们知道Redis实现锁的原理在于 SETNX命令。当 key不存在时将 key的值设为 value ,返回值为 1;若给定的 key已经存在,则 SETNX不做任何动作,返回值为 0 。 SETNX key value 我们来设想一下这个场景:A、B两个线程来尝试给key myLock加锁,A线程先拿到锁(假如锁3秒后过期),B线程就在等待尝试获取锁,到这一点毛病没有。 那如果此时业务逻辑比较耗时,执行时间已经超过redis锁过期时间,这时A线程的锁自动释放(删除key),B线程检测到myLock这个key不存在,执行 SETNX命令也拿到了锁。 但是,此时A线程执行完业务逻辑之后,还是会去释放锁(删除key),这就导致B线程的锁被A线程给释放了。 为避免上边的情况,一般我们在每个线程加锁时要带上自己独有的value值来标识,只释放指定value的key,否则就会出现释放锁混乱的场景 一般我们可以设置value为业务前缀_当前线程ID或者uuid,只有当前value相同的才可以释放锁 锁过期了,业务还没执行完 redis分布式锁过期,而业务逻辑没执行完的场景,不过,这里换一种思路想问题,把redis锁的过期时间再弄长点不就解决了吗? 那还是有问题,我们可以在加锁的时候,手动调长redis锁的过期时间,可这个时间多长合适?业务逻辑的执行时间是不可控的,调的过长又会影响操作性能。 要是redis锁的过期时间能够自动续期就好了。 为了解决这个问题我们使用redis客户端redisson,redisson很好的解决了redis在分布式环境下的一些棘手问题,它的宗旨就是让使用者减少对Redis的关注,将更多精力用在处理业务逻辑上。 redisson对分布式锁做了很好封装,只需调用API即可。 1 RLock lock = redissonClient.getLock("stockLock"); redisson在加锁成功后,会注册一个定时任务监听这个锁,每隔10秒就去查看这个锁,如果还持有锁,就对过期时间进行续期。默认过期时间30秒。这个机制也被叫做:“看门狗” redis主从复制的坑 redis高可用最常见的方案就是主从复制(master-slave),这种模式也给redis分布式锁挖了一坑。 redis cluster集群环境下,假如现在A客户端想要加锁,它会根据路由规则选择一台master节点写入key mylock,在加锁成功后,master节点会把key异步复制给对应的slave节点。 如果此时redis master节点宕机从节点复制失败,为保证集群可用性,会进行主备切换,slave变为了redis master。B客户端在新的master节点上加锁成功,而A客户端也以为自己还是成功加了锁的。另外如果主从复制延迟同样也会造成加锁和解锁延迟的问题。 此时就会导致同一时间内多个客户端对一个分布式锁完成了加锁,导致各种脏数据的产生。 毕竟redis是保持的AP而非CP,如果要追求强一致性可以使用zookeeper分布式锁。 本文分享自华为云社区《redis分布式锁?易踩得坑》,原文作者:minjie 。 点击关注,第一时间了解华为云新鲜技术~

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册