精华内容
下载资源
问答
  • 注:论文发表于《包装工程》杂志2017年第6期“工业设计”栏目。虽然是17年才发表,但这篇论文其实是很早...摘 要:目的 研究产品交互设计中场景理论。方法 通过阐述交互设计各阶段中客观场景、目标场景、实际场景...

    注:论文发表于《包装工程》杂志2017年第6期“工业设计”栏目。虽然是17年才发表,但这篇论文其实是很早之前写的,所以用的案例比较老。

     

    ____________________________________

    作者:胡伟峰;王玉梅;汤进;李世国

    (江南大学,无锡, 214122)

    摘 要:目的 研究产品交互设计中场景理论。方法 通过阐述交互设计各阶段中客观场景、目标场景、实际场景的含义及其应用。结论 指出了场景理论对交互设计的价值与意义,并提出了动态思维:场景设计是一个循环设计流程;主次思维:抓主要场景,统筹次要场景;拆解思维:复杂的大场景由众多小场景组成三大基于场景理论的交互设计思维。

    关键词:用户场景;交互设计;

    中图分类号:TB472 文献标识码:A

    “场景(scenarios) ”一词常见应用于戏剧领域中,指在一定的时间、空间内发生的一定的任务行动或生活画面。【1】在交互设计领域,基于场景设计(scenario-based design) 的思想最早由Carroll提出,强调将设计工作的焦点从定义系统的操作转变到描述什么人将使用该系统去完成其任务。【2】交互设计改变了设计中以物为对象的传统,直接把人类的行为作为设计对【3】人使用产品必须有一定的行为,这种行为是在一定场景下进行的, 行为的完成需要一定技术的支持,因而人、行为、场景和技术4个要素构成了所谓的交互系统。【4】场景是交互系统中极其重要的要素,研究在一定场景下的用户行为,对用户行为逻辑针对相应的场景进行规划和设计,是交互设计的重要目标。

     

    1 交互设计各阶段中场景的种类及其应用

    场景描述了关于操作者、操作者及其环境的背景信息、操作者的目的或目标、一系列活动和事件等内容,【5】这里的操作者即指的是产品的使用用户。基于场景理论的交互设计,是指在交互设计整个过程中使用场景描述的方法来具体地描述用户对产品的使用情况。如图1,交互设计各阶段可分为不同的用户场景,包括早期用户需求分析阶段的客观场景,产品交互设计阶段的目标场景以及场景验证和评估阶段的实际应用场景。


    图1 用户场景种类及其设计流程

    Fig1 User scene type and its design process

     

    1.1 客观场景

    设计师在交互设计的开始阶段,需要对用户现状及其需求进行分析。客观场景便是通过对用户现状的调查研究,从中获取有效信息进行总结和归纳出来的。客观场景的构建,最常见的调研方法是:用户现场观察法。在观察的同时,设计师可以对观察中遇到的问题进行总结和分析,通过观察后结合用户访谈等方式来补充分析用户的需求。

    比如在“快的打车”等打车类APP未投入市场之前,用户的典型客观场景可以描述为:公司职员王先生晚上6:00下班(操作者及其背景信息),需要打车回家(操作者的目标),在公司门口招揽出租车,可是一直招揽不到出租车,最终走了两公里路到附近的商场才打到了车,而且发现商场附近待揽客的出租车非常多,王先生觉得非常郁闷,为什么资源不匹配呢(操作者的一些列活动、感受等)。

     


     

    上述对用户“打车”这一客观场景的描述,是建立在对一定量“打车”用户调研的基础之上描述出的典型场景。客观场景是为了描述目标用户和客观状况而总结的,强调的不仅仅是问题点,还包括产品的目标用户描述、用户客观行为流程、用户情感表现、问题点等。设计师可以通过客观场景中分析出用户的需求,包括行为流程上的体验问题及其对应的设计机会点等。

    1.2 目标场景

    在产品交互设计阶段,需要设计师构建目标场景。目标场景,是建立在客观场景之上,设计师所期望达成的能解决用户客观场景中相关需求的用户场景。在客观场景的基础之上,设计师可以结合相关交互理论和设计准则,以及通过可用性和场景实验等方法,对客观场景进行分析和研究,进而设计和规范出能够满足用户需求的目标场景。目标场景从表达形式上可以细分为行为场景和交互场景。

    行为场景,是指在客观场景研究的基础之上,对用户的行为流程进行分析和描述的场景,常用场景故事版等表现工具进行描述;如图2,设计师勾勒出的“快的打车”投入市场后的目标行为场景故事版。结合场景故事版,用户的典型目标场景可以被描述为:公司职员王先生晚上6:00下班,需要打车回家。王先生在5:50时,打开“快的打车”APP可以看到公司附近有很多出租车,王先生输入出发地和目的地确认打车。30秒后出租车司机李师傅接单,王先生可以在手机上清晰的看到李师傅的车辆位置,10分钟后王先生成功上车。到达目的地后,王先生用手机在线支付了打车费,开心的回到家陪女儿吃晚饭。

    图 2 “快的打车”目标场景故事版

    Fig2 Story version of “Quick taxi ”target scene

    交互场景则是指产品在被用户使用过程中的场景,常用信息流程图、低保真页面流程图、使用流程故事版等工具进行描述。【6】以“快的打车”为例,用户在移动场景下不方便打字,所以设计了语音输入和快速搜索来确定家和公司的位置;移动场景下容易出错,所以设计了信息确认机制;在等待应答的过程中,可视化告知用户APP通知的车辆数和距离,并且在打车成功后告知车辆距离和时间,消除用户等待的焦虑,将信息可视化。

     

     

    图 3 “快的打车”交互场景

     

    Fig3 Interaction scene of “Quick taxi ”

    所设计的目标场景需要针对用户在客观场景中反应的需求提出针对性的解决方案。通过目标场景设计,设计师可以勾画出未来用户和产品之间理想的行为交互模型。

    1.3 实际场景

    在实际产品交互设计阶段,目标场景会有很多,不同设计师设计出的目标场景也不同。如何验证和评估目标场景的优劣,就需要引入实际场景。实际场景是指在设计师不干预的情况下,提供目标场景中设计好的相关产品或模型给用户,由用户在实际的参与式体验过程中测试目标场景,进行产品的测试及适用性评价【7】。通过这个评价过程,设计师可以进一步观察用户和产品之间存在的其他关系,并为产品最终设计方案提供场景参考。【8】

    2 用户场景对交互设计的价值与意义

    在产品交互设计中,设计师设计的对象是用户的行为。用户行为是动态的,建立在一定场景上的用户行为才有意义。因此在对用户行为进行设计时,需要设计师意识到研究和应用基于场景设计的价值和意义。

    2.1 更准确地把握产品和用户之间的关系及其用户需求

    以用户为中心的产品设计,【9】强调需求来源于用户,需求转化出的设计方案最终服务于用户。设计师可以通过观察用户和产品的互动行为,通过客观场景描述,直观的展现出用户和产品之间的互动关系及其问题。这些关系和问题是用户需求的直观体现,客观场景描述了目标用户、用户客观行为流程、用户情感表现、问题点等信息,而且场景具有故事性,是通过一段段的故事片段描述构成的,因此场景描述相对于其他用户研究总结出来的客观数据、需求文档等更生动和直观。直观而且形象的客观场景描述,便于设计师和其他产品设计人员更准确和细致的把握客观用户需求。

     

    2.2 提升交互设计方向的合理性和产品满意度

    在产品交互设计阶段,通过对目标场景的设计和描绘,设计师可以基于场景进行交互设计,通过场景故事版、用户体验旅程图、信息流程图、低保真页面流程图等工具细化用户在客观场景中所反映出来的需求并给出解决方案。因此基于场景的交互设计,一方面更加全面的分析和解决用户的需求,避免单一分析用户行为或者产品功能造成的对用户需求的遗漏。同时,通过实际场景中对目标用户场景的验证和评估,提升了产品交互设计方向的合理性;另一方面,设计师设计的目标场景将用户的情感表现等需求直观化和故事化,使得设计师所设计的产品设计点更容易被用户感受,提升产品的满意度。

    3 基于用户场景的产品交互设计的设计思维

    3.1 动态思维:场景设计是一个循环设计流程

     

    图4 交互设计中场景设计的动态思维

     

    Fig4Dynamic thinking of scene design in interactive design

    用户场景不是固定不变的。【10】如图4,在交互设计各阶段中,客观场景是目标场景的设计基础,实际场景对目标场景进行验证和评估。同时,被验证的实际场景又是下一次交互设计的设计对象,上一次的实际场景会转化为下一次的客观场景。因为在实际场景验证和评估中,总会遇到不符合用户预期,目标场景中没有考虑到的用户需求的问题。需要指出的是,掌握交互设计中场景设计的动态思维,并不是指这个设计流程是无限循环的,场景设计是一个持续优化和快速迭代的过程,设计师及其相关产品负责人需要讨论出每个迭代阶段具有共识性的目标场景和实际场景的评估标准。面对既定的迭代阶段目标,在整个设计循环流程中,一旦满足相关目标场景及其实际场景评估标准,现有迭代阶段的交互设计便可终止。

     

    3.2 主次思维:抓主要场景,统筹次要场景

    在客观场景分析和目标场景设计过程中。分析场景时,需要区分主要场景和次要场景。在交互设计各阶段不同场景中,必有而且只有一种场景居于支配的地位,起着规定或影响其他场景的作用,这种场景就是主要场景,其他场景则是次要场景。在分析和解决、处理用户需求时,既要看到主要场景的重要性,善于抓住重点,又要看到次要场景的客观影响,学会全面地看待用户需求,做到抓主要场景,统筹次要场景的统一。主次思维,把握主要场景,同时兼顾次要场景,可以有效地保证基于场景分析的交互设计的产品设计的准确性。

    3.3 拆解思维:复杂的大场景由众多小场景组成

    用户场景有大有小,用户的客观大场景总是由众多可以层级细分的小场景组成。在客观场景分析过程中,大场景相对宏观,可以总览用户的宏观需求。而小场景更加聚焦,可以分析出用户更加具体需求,同时,小场景更加具象,能够落实到用户的具体行为流程和对产品的细节体验,便于设计师有针对性且具象的针对客观小场景进行目标场景设计。比如用户用“快的打车”叫出租车的场景就是大场景,这个大场景中包含用户叫车场景,司机接单场景,用户付款场景等等小场景。用户叫车场景还可以细分为用户当前位置定位场景、用户输入目的地地址场景、用户立即叫车或预约叫车场景等。越细分的客观场景,越有利于设计师针对性的设计出有效的目标场景,同时也更有利于在实际场景中进行交互模型评估和场景验证。所以,在交互设计各阶段应用场景理论进行设计时,需要具备拆解思维,将复杂的大场景拆分为众多可设计的小场景,再由众多的目标小场景,组成最终的目标大场景,进行实际场景验证,输出最终的交互设计成果。

    4 结语

    现在产品和用户体验日趋复杂,传统的物理逻辑层面的设计已经不能满足用户的需要,要关注“事”,【11】场景作为交互系统中极其重要的要素,研究交互设计中的场景理论,从产品交互设计各阶段入手,将场景理论深入到交互设计的各个阶段,是对现有的交互设计实践的一次深化。同时,掌握交互设计中运用场景理论时的循环思维、主次思维和拆解思维,可以有效地把握产品和用户之间的关系及其用户需求,提升交互设计方向的合理性和用户对产品的满意度。研究交互设计中的场景理论,具有非常重要的价值和意义。

     

    参考文献

     

    [1] 沈贻炜. 影视剧创作[M].浙江:浙江大学出版社, 2012.

    SHEN Yiwei. Film and television drama creation[M]. Zhejiang: Zhejiang University press,2012

    [2]Carroll J M. Five reasons for scenario-based design[J]. Interacting with Computers, 2000(13):43–60.

    [3]辛向阳. 交互设计:从物理逻辑到行为逻辑[J]. 装饰, 2015(01):58-62.

    XIN Xiangyang.Interaction Design: From Logic of Things to Logic of Behaviors [J].2015.1:58-62.

    [4]李世国, 费钎. 和谐视野中的产品交互设计[J]. 包装工程, 2009(01):137-140.

    LI Shiguo, FEI Qian. Product Interaction Design in the Perspetive of Harmony [J].Packaging Engineering, 2009(01):137-140

    [5]Go K. , Carroll J. M. , Imamiya A. . Surveying scenario based approaches in sys tem design[J] . IPSJSIG Notes, HI878, 2000:43-48.

    [6]赵婉茹. 浅谈场景故事在用户体验设计中的应用[J]. 设计, 2014(09):174-175.

    ZHAO Wanru.The Application of Scenario Stories in User Experience Design [J].Design, 2014(09):174-175.

    [7] 诺曼·唐纳德 A.设计心理学[M].北京:中信出版社,2010.

    NORMAN D A.The Design of Everyday Things[M].Beijing:China CITIC Press,2010.

    [8]DDF·UXPA中国. 用户体验百家谈[M] .北京:电子工业出版社, 2014.

    DDF·UXPA China. User experience a hundred talk[M] .Beijing:Electronics Industry Press,2014

    [9]罗仕鉴, 胡一. 服务设计驱动下的模式创新[J]. 包装工程, 2015(12).1-4.

    LUO Shijian,HU Yi.Model Innovation Driven by Service Design[J]. Packaging Engineering, 2015(12).1-4.

    [10]COOPER A.软件观念革命——交互设计精髓[M].北京:电子工业出版社,2012.

    COOPER A. Software Concept Revolution: the Essence of Interaction Design[M]. Beijing: Publishing House of Electronics Industry,2012.

    [11] 安娃. 交互设计思维在服务体验中的应用[J]. 包装工程, 2015, 02期(02):5-8.

    AN Wa. Collaborative Design of Product Interaction Design System[J].Packaging Engineering,2015,02(02):5-8.

    转载于:https://www.cnblogs.com/xjmnet/p/9377274.html

    展开全文
  • 产品场景化设计

    千次阅读 2019-11-05 21:00:28
    前言 本文围绕什么场景化设计,有哪些场景化设计的例子,为什么要进行...互联网产品场景” 分为两类 第一类,为了实现用户目标而产生的场景,这种类型的场景需要明确用户目标,可能并不需要涵盖用户是怎么实...

    前言

    本文围绕什么是场景化设计,有哪些场景化设计的例子,为什么要进行场景化设计和场景化设计的具体方法展开解读,本文篇幅较长,请合理利用时间阅读。

    什么是场景化设计

    生活中,场景就像戏剧、电影中的场面,泛指情景。在戏剧或影视剧里,场景由人物,时空,事件(行为),环境(社会环境和自然环境)等等要素构成,产品的场景化则根据场景来设计而已。​

    1. 互联网产品 “场景” 分为两类

    第一类,为了实现用户目标而产生的场景,这种类型的场景需要明确用户目标,可能并不需要涵盖用户是怎么实现目标的,这类场景指根据用户的精准需求,为其提供精准服务,用明确的差异化服务给用户提供一个使用产品的动机。

    第二类,则是更加精细化的场景,这类场景需要明确用户操作流程,本文主要针对这类场景展开解读。

    2. 总结

    场景化设计指基于对场景的分析,得出用户痛点与需求,结合前后场景预判用户目标,通过设计提高用户效率,给予用户惊喜与感动。

    有哪些场景化设计的例子

    下面,我会结合一些做的比较好的产品,进行分析。

    1. 人是变量

    “使用产品的用户不同,所看到的信息也不同”,随着大数据和智能推荐技术的普及,越来越多的产品通过挖掘不同用户的喜好,生成用户画像,为每位用户提供 “千人千面” 的个性化内容,这样的产品大家都很熟悉,比如抖音,淘宝,微博,今日头条。

    2. 时间是变量

    “使用产品的时间不同,所看到的信息同样也不同”,比如小米手机 MIUI11 效率革新功能「智能出行」,当在旅游、出行类APP上设置好行程后,MIUI11 会根据出行时间自动将该行程记录推送到消息栏并同步日历。当然,出行类APP都会做这个事情。
    在这里插入图片描述
    还有蚂蚁森林的页面会根据用户打开的时间进行变化(白天与夜晚模式)等等,这些都是充分考虑了场景中时间这一变量,才有如此高效暖心的设计。

    3. 地点是变量

    “同一个用户,在不同的地点看到的信息也不同”,就像大众点评APP当用户从常住地北京定位成非常住地杭州时,根据用户的上个场景与当前场景预测用户可能处于旅游状态,从而预测用户下一步的目标是在杭州「吃喝玩乐」,所以首页和攻略页的内容都发生了变化,为用户推荐旅行地的「吃喝玩乐」:
    在这里插入图片描述
    4. 环境是变量

    “不同的环境,所看到的信息也不同”,比如设备环境发生变化时:IOS13 中的备忘录页面,将「添加」按钮移到了右下角,为什么?因为手机屏幕越来越大,把按钮从右上角移到右下角,更有利于用户单手操作:
    在这里插入图片描述
    再比如,我们在驾驶环境下,要保持注意力集中,避免或减少分心驾驶导致的交通事故,所以基于驾驶环境 IOS11 上线了驾驶模式功能,当 iPhone 与车内 USB 或 蓝牙连接或 iPhone 感知到人的移动速度时,iPhone 就会自动进入驾驶模式:

    在该模式下,任何人发短信,我们都不会收到提示,对方会收到 “我正在驾驶,稍后回复您” 的自动回复。并且同时,iPhone 还会会追加一条短信,提示对方只要回复 “紧急” 关键词,我们就能立刻接收到他们的消息提示:
    在这里插入图片描述
    iPhone 的场景化设计非常优秀,还有很多地方本文没有提到,感兴趣的自己去研究体验。

    为什么要基于场景做设计

    读者既然看到了这里,那么你心中一定会认可 场景化设计 ,但由于与用户的空间相隔,我们无法感知用户在真实场景中使用产品的具体情况,也就是说,我们需要对用户使用场景进行分析与预期,探索新的设计与交互。

    怎么进行场景化设计

    既然基于场景化设计这么好,那么我们该从什么地方入手呢?或者说我们该怎么进行设计?

    请读者带着这些问题,一起来看如下4个步骤

    1. 根据用户使用流程和行为路径穷尽场景

    根据用户的使用流程和行为路径列举场景,这里以乘坐飞机(手机购票)为例,列举乘坐飞机涉及到的关键场景:
    在这里插入图片描述
    ① 乘客在航旅纵横页面购票,航班多查找起来会很麻烦。

    ② 乘客起大早拖着疲惫的身体在去往机场的路上,结果又遇到早高峰堵车,内心焦躁烦闷。

    ③ 起飞前乘客在机场过安检,安检流程复杂,又检测出不符合登机规定的物品,让人心烦,手忙脚乱。

    ④ 起飞前,乘客在候机口候机,人多嘈杂,没有座位,还背着繁重的行李,还要时刻关注航班信息。

    ⑤ 快起飞前,乘客背着行李排队,将登机牌和身份证出示给工作人员,工作人员站在入口处开始检查每位乘客的登机牌和身份证。

    ⑥ 检完票后,乘客拿着身份证和登机牌,背着行李乘坐摆渡车,摆渡车上嘈杂、拥挤。

    ⑦ 下摆渡车后,乘客拿出登机牌,背着行李排队检票登机,工作人员站在飞机前开始检查每位乘客的登机牌。

    ⑧ 在起飞前30分钟,乘客登机,背着行李在狭窄拥挤的通道里寻找自己的座位。找到座位后,将沉重的行李艰难的放到上方的置物架上。放好行李后,坐到自己的座位上,系好安全带,调节座椅靠背,等待飞机起飞。

    ⑨ 飞行过程中,气流导致飞机颠簸,乘客感到恐慌不适。飞行过程中,乘客通过看电影,看书,睡觉打发时间。

    ⑩ 到达目的地,乘客从高处置物架上取下行李,拿着沉重的行李排队下飞机。此时乘客对目的地的天气等其他情况都不清楚。

    ⑪ 乘客走出飞机到达航站楼后,在陌生的机场,跟着标牌指示艰难的找到自己的行李。拿着行李跟着指示牌困难的找出口。

    通过对关键场景的详细描述,我们将摸不着的用户场景像过电影一样在眼前一一呈现,有利于我们发现很多想不到或者通过调研得不到的细节,帮助我们发现用户真正的痛点与需求,洞察设计机会点。

    2. 根据场景挖掘机会点

    完成了第一步的场景列举,我们对流程中涉及的场景有了深刻的了解,下一步就是对场景的判断与分析,挖掘机会点。机会点挖掘有两个方向,一是通过分析当前场景存在的痛点和需求挖掘机会点,二是通过对用户下一步目标的预判寻找机会点。

    ① 通过分析当前场景存在的痛点和需求挖掘机会点

    我们手机中都有支付宝,支付宝「朋友」界面,当用户输入某数值时,输入框上方会自动显示「给对方转账XXX元」按钮,用户可点击该按钮完成转账。

    这是因为经常有用户误以为输入数值发送即完成了转账,导致很多尴尬出现。基于该场景下的痛点与需求,支付宝做了这个改进,即避免了尴尬的发生,又很贴心。

    IOS 系统在切换APP操作时,会将一些金融类APP虚化,以此来保证用户信息安全。这一设计细节也是充分考虑了用户在切换APP时的场景,解除了用户在公告场合担心被窥屏而泄露个人财富信息的担忧。
    在这里插入图片描述在这里插入图片描述
    还有,当我们用耳机听音乐或播放视频时,拔下耳机,声音就会自动停掉,这样就算在安静的场合听音乐或者看视频,耳机不小心掉下来也不会发出尴尬的声音,这些都是充分考虑了用户当前使用时的场景,才做出如此贴心的设计。

    ② 通过对用户下一步目标的预判寻找机会点

    该方法是通过对用户当前场景的分析,预判用户下一步的行为与目标,从而寻找当前场景的机会点。

    如何预期用户下一步目标?有三个方法:

    1. 通过成组动作进行预期,如复制—粘贴,编辑—保存操作。
    2. 通过用户认知流程预判,如,浏览时反向滑动→结束浏览/回到顶部;再比如谷歌翻译在发音时,第一遍是正常语速,第二遍语速变慢,第三遍又恢复到常速,是不是很贴心,很符合用户期望?
    3. 通过产品使用流程进行预期,如订外卖—取外卖—评价。

    例如:在谷歌浏览器,当我们打开多个浏览窗口时,通常需要手动一个个地关闭标签页。

    Google Chrome 充分考虑到了用户的该使用场景,当用户关闭一个标签页时,预期用户会关闭下一个标签页,所以当关闭一个标签时,相邻标签会自动靠近,保证关闭的按钮始终位于鼠标的当前位置,这样用户就不用移动鼠标关闭下一个标签页,提高了用户的使用效率。

    3. 机会点转化为落地的设计方案

    在将机会点转化为具体的设计时,有两个可作为依据的设计原则,分别为 高效、情感化,我们分别阐述二者。

    —— 实现高效有以下几个方法:——

    ① 行动点前置

    通过对用户下一目标的预测,将用户目标在当前场景展示,缩短操作流程,达到高效的目标。如淘宝首页的 Tab 栏会根据每个用户的浏览记录预测用户目标,千人千面个性化展现,缩短了用户查找商品的路径,提高商品购买效率。
    在这里插入图片描述
    ② 行动点置换

    还是拿淘宝举例,淘宝底部的第一个导航,当用户滑动首页下方的商品流时,该按钮由首页变成置顶。
    在这里插入图片描述
    ③ 行动点相关提示

    意思是根据用户当前目标或下一步目标进行相关的提示。如支付宝朋友页面,当上滑时,会出现「找人转账」的提示,点击进入朋友列表的纯净模式(去掉了服务通知等跟转账无用的列表),提高了用户寻找的效率。

    在这里插入图片描述
    再比如,网易邮箱,当邮件中提到附件,但是没有上传附件时,点击发送后,系统弹出下方的提示,解决了用户常常忘记添加附件的困扰。
    在这里插入图片描述
    ④ 突出行动点

    根据用户当前目标或下一步目标突出关键按钮,帮助用户快速找到关键操作,吸引用户点击,降低了用户思考成本,提升效率。运用这个方法进行设计的例子太多了,比如淘宝的商品详情页用红色突出购买按钮等。

    ⑤ 直接执行

    根据用户当前目标或下一步目标直接执行。比如滴滴的扫一扫界面,当检测到光线较暗时,手电筒会自动打开,提高了扫一扫的效率。
    在这里插入图片描述
    还有微信扫一扫功能,同样当光线较暗时自动打开手电筒,非常的贴心。

    —— 实现情感化有以下几个方法:——

    唐纳德·诺曼在《情感化设计》中提到设计的三个层次,分别为:本能的设计,行为的设计,反思的设计,情感化设计是能打动人的,它能传递感情,勾起回忆,给人惊喜,情感化设计帮助产品与用户之间建立情感的纽带,能强化用户对品牌的认知,培养对品牌的忠诚度。

    情感化设计的步骤依次为:提炼影响产品的的情感指标 → 聚焦用户对产品的情感诉求 → 产出设计方案 → 验证设计价值(来源于周姮—知乎蚂蚁金服体验技术部的一次分享)。

    例如:网易云音乐会获取用户的生日,在用户生日时会变成「生日快乐」的蛋糕样式,点击进去的音乐列表,第一首歌就是生日快乐歌,让人心里暖暖的。
    在这里插入图片描述
    有情感化设计的产品很多,比较感性的人群更容易起到作用。

    4. 设计检验

    最后一步就是设计方案的验证,设计方案能否帮助用户缩短操作流程?降低用户思考成本?帮助用户高效的完成任务?是否能打动用户给他们带来惊喜与温暖?

    通过可用性测试及上线后的数据反馈,帮助我们更好的优化设计方案。

    展开全文
  • 其实在某些时候,这两个特殊的类的使用是可以互为替换的,但是在较大规模的系统工程设计时,如果不能正确运用好它的话,可能会破坏程序的结构,增强模块间的耦合度,给程序的维护与升级带来较大的不便,希望大家能够...
    abstract class和interface 是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。
    abstract class和interface 之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,因此很多开发者在进行抽象类定义时对于abstract class和interface的选择显得比较随意。其实,两者之间还是有很大区别的,对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意图的理解是否正确、合理。我认为正确运用好抽象类和接口,可以优化软件结构的设计,对软件的扩展、维护带来很大的便利。
    本文将对它们之间的区别进行一番剖析,试图给开发者提供一个在二者之间进行选择的依据。
    首先来理解一下抽象类。在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
    比如我们xpads 项目中的交易类就可以理解为一个抽象类,即期交易、远期交易、掉期交易等都是继承交易类的具体类。即期交易、远期交易、掉期交易这些具体概念是实际存在的,而交易这个概念在问题领域中是不存在的,可以理解为一个抽象概念。正是因为抽象概念在实际问题领域中没有东西与它对应,所以用以表征抽象概念的抽象类是不能被实例化的。
    接下来理解一下接口,接口是面向对象设计中的一组规范,是一组方法的集合体(也可以定义一些常量),在一些软件设计模式中提倡的面向接口编程,其实就是屏蔽实现类的内部处理,增强模块的安全性、灵活性,达到软件设计的高内聚、松耦合。
    下面从三个方面进行比较:
    一、从语法定义层面看abstract class和interface
    使用abstract class的方式定义Deal抽象类的方式如下:
     
    Java代码  
    1. abstract class  FxDeal {  
    2.     private long dealsId;  //交易流水号  
    3.     private long blockNumber;//套流水号  
    4.     private String appls;//产品类别  
    5.     private String inputChannel;//录入渠道  
    6.     private String typeOfDeal;//交易类型  
    7.     private String flagOfDeal;// 特殊交易标识  
    8.     private String bankId;//业务发生行  
    9.     private String customerId; //客户号  
    10.     private String customerName;//客户名称  
    11.     private int customerType;//客户类型  
    12.     private double amount1;  
    13.     private double amount2;  
    14.     abstract void method1();  
    15.     abstract void method2();  
    16.                …  
    17. }  
      使用interface的方式定义Deal抽象类的方式如下:
     
     
    Java代码  
    1. interface FxDeal {  
    2.   void method1();  
    3.   void method2();  
    4.   …  
    5. }  
      abstract class 方式中, Deal 可以有自己的数据成员,也可以有非 abstarct 的成员方法,而在 interface 方式的实现中, Deal 只能够有静态的不能被修改的数据成员(也就是必须是 static final 的,不过在 interface 中一般不定义数据成员),所有的成员方法都是 abstract 的。从某种意义上说, interface 是一种特殊形式的 abstract class
    二、从编程层面看abstract class和interface
    首先,abstract class在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。
    其次,在abstract class的定义中,我们可以赋予方法的默认行为。但是在interface的定义中,方法却不能拥有默认行为,为了绕过这个限制,必须使用委托,但是这会增加一些复杂性,有时会造成很大的麻烦。
    在抽象类中不定义默认行为存在一个比较严重的问题,那就是可能会造成维护上的麻烦。因为如果后来想修改类(一般通过abstract class或者interface来表示)以适应新的情况(比如,添加新的方法或者给已用的方法中添加新的参数)时,就会非常的麻烦,可能要花费很多的时间(对于派生类很多的情况,尤为如此)。但是如果它是通过abstract class来实现的,那么可能就只需要修改定义在abstract class中的默认行为就可以了。
    另一个问题是:如果不是采用抽象类中的默认行为,就会导致同样的方法实现出现在该抽象类(或接口)的每一个派生类(或实现类)中,违反了“one rule,one place”原则,造成代码重复,同样不利于以后的维护。因此,我认为在abstract class和interface间进行选择时还是需要谨慎的,搞不好的话,是会给程序埋下一些隐患的。
    三、从设计理念层面看abstract class和interface
             abstract class在Java语言中体现的是一种继承关系,父类和派生类之间必须存在“is a”关系,即父类和派生类在概念本质上应该是相同的。对于interface 来说则不然,并不要求interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了interface定义的契约而已。为了使论述便于理解,下面将通过一个简单的实例进行说明。
      考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:
      使用abstract class方式定义Door:
     
    Java代码  
    1. abstract class Door {  
    2.   abstract void open();  
    3.   abstract void close();  
    4. }  
    使用interface方式定义Door:
     
     
    Java代码  
    1. interface Door {  
    2.   void open();  
    3.   void close();  
    4. }  
      其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。
     
     
      如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在本例中,主要是为了展示abstract class和interface反映在设计理念上的区别,其他方面无关的问题都做了简化或者忽略),下面将罗列出可能的解决方案,并从设计理念层面对这些不同的方案进行分析。
      解决方案一:
      简单的在Door的定义中增加一个alarm方法,如下:
     
    Java代码  
    1. abstract class Door {  
    2.   abstract void open();  
    3.   abstract void close();  
    4.   abstract void alarm();  
    5. }  
     或
    Java代码  
    1. interface Door {  
    2.   void open();  
    3.   void close();  
    4.   void alarm();  
    5. }  
      那么具有报警功能的AlarmDoor的定义方式如下:
    Java代码  
    1. class AlarmDoor extends Door {  
    2.   void open() { … }  
    3.   void close() { … }  
    4.   void alarm() { … }  
    5. }  
     或者
    Java代码  
    1. class AlarmDoor implements Door {  
    2.   void open() { … }  
    3.   void close() { … }  
    4.   void alarm() { … }  
    5. }  
      这种方法违反了面向对象设计中的一个核心原则ISP(Interface Segregation Priciple),在Door的定义中把Door概念本身固有的行为方法和另外一个概念“报警器“的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为“报警器“这个概念的改变(比如:修改alarm方法的参数)而改变。
     
      解决方案二:
      既然open、close和alarm属于两个不同的概念,根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用abstract class方式定义;两个概念都使用interface方式定义;一个概念使用abstract class方式定义,另一个概念使用interface方式定义。
      显然,由于Java语言不支持多重继承,所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。
    如果两个概念都使用interface方式来定义,那么就反映出两个问题:1、我们可能没有理解清楚问题领域,AlarmDoor在概念本质上到底是Door还是报警器?2、如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用interface方式定义)反映不出上述含义。
      如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract class在Java语言中表示一种继承关系,而继承关系在本质上是“is a”关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示:
    Java代码  
    1. abstract class Door {  
    2.   abstract void open();  
    3.   abstract void close();  
    4. }  
    5.   
    6. interface Alarm {  
    7.   void alarm();  
    8. }  
    9.   
    10. class AlarmDoor extends Door implements Alarm {  
    11.   void open() { … }  
    12.   void close() { … }  
    13.   void alarm() { … }  
    14. }  
      这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实abstract class表示的是“is a”关系,interface表示的是“like a”关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。
    其实在某些时候,这两个特殊的类的使用是可以互为替换的,但是在较大规模的系统工程设计时,如果不能正确运用好它的话,可能会破坏程序的结构,增强模块间的耦合度,给程序的维护与升级带来较大的不便,希望大家能够细细体会。
    展开全文
  • redis使用场景及案例

    万次阅读 多人点赞 2019-08-19 14:49:30
    最近在写一个篮球社区项目,其中redis的使用场景还挺多的,于是结合项目总结一下redis的使用场景 一、缓存 项目场景:用户登录或注册时的验证码存储,用户名 set Code:1:code 1232 EX 100 NX OK get Code...

    最近在写一个篮球社区项目,其中redis的使用场景还挺多的,于是结合项目总结一下redis的使用场景

    一、缓存

    项目场景:用户登录或注册时的验证码存储,用户名

    set Code:1:code 1232 EX 100 NX

    OK

    get Code:1:code

    “1232”

    set User:1:name bob EX 100 NX

    OK

    get User:1:name

    “bob”
    缓存是 redis 出镜率最高的一种使用场景,仅仅使用 set/get 就可以实现,不过也有一些需要考虑的点
    1、如何更好的设置缓存
    2、如何保持缓存与上游数据的一致性
    3、如何解决缓存雪崩,缓存击穿问题(这两个问题会单独写一篇)

    二:消息队列

    lpush UserEmailQueue 1 2 3 4

    lpop UserEmailQueue

    rpop UserEmailQueue

    1

    rpop UserEmailQueue

    2

    可以把redis的队列看为分布式队列,作为消息队列时,生产者在一头塞入数据。消费者另一条取出数据:(lpush/rpop,rpush/lpop),不过也有一些不足,而这些不足有可能是致命的,不过对于一些丢几条消息也没关系的场景还是可以考虑的
    1、没有ack(消息确认机制),有可能丢消息
    2、需要做redis的持久化配置
    用redis实现消息队列

    三:过滤器(dupefilter)

    sadd UrlSet http://1
    (integer) 1
    sadd UrlSet http://2
    (integer) 1
    sadd UrlSet http://2
    (integer) 0

    smembers UrlSet

    1. “http://1”
    2. “http://2”
      scrapy-redis作为分布式的爬虫框架,便是使用了 redis 的 Set 这个数据结构来对将要爬取的 url 进行去重处理。
    def request_seen(self, request):  
      """Returns True if request was already seen.   
       Parameters    
       ----------   
        request : scrapy.http.Request    
        Returns    
        -------
         bool    
         """    
         fp = self.request_fingerprint(request)    
         added = self.server.sadd(self.key, fp)    
         return added == 0
    

    不过当 url 过多时,会有内存占用过大的问题

    四、分布式锁

    分布式锁,这个是除了 KV 缓存之外最为常用的另一个特色功能。

    set Lock:User:10086 06be97fc-f258-4202-b60b-8d5412dd5605 EX 60 NX
    释放锁,一段 LUA 脚本
    
    if redis.call("get",KEYS[1]) == ARGV[1] then
    	  return redis.call("del",KEYS[1])
    else
    	 return 0
    end
    

    这是一个最简单的单机版的分布式锁,有以下要点
    1)EX 表示锁会过期释放
    2)NX 保证原子性
    解锁时对比资源对应产生的 UUID,避免误解锁
    当你使用分布式锁是为了解决一些性能问题,如分布式定时任务防止执行多次 (做好幂等性),而且鉴于单点 redis 挂掉的可能性很小,可以使用这种单机版的分布式锁。
    举个例子说明:
    比如一个很能干的资深工程师,开发效率很快,代码质量也很高,是团队里的明星。所以呢诸多产品经理都要来烦他,让他给自己做需求。如果同一时间来了一堆产品经理都找他,它的思路呢就会陷入混乱,再优秀的程序员,大脑的并发能力也好不到哪里去。所以呢他就在自己的办公室的门把上挂了一个请勿打扰的牌子,当一个产品经理来的时候先看看门把上有没有这个牌子,如果没有呢就可以进来找工程师谈需求,谈之前要把牌子挂起来,谈完了再把牌子摘了。这样其它产品经理也要来烦他的时候,如果看见这个牌子挂在那里,就可以选择睡觉等待或者是先去忙别的事。如是这位明星工程师从此获得了安宁。

    一定要设置这个过期时间,因为遇到特殊情况 —— 比如地震(进程被 kill -9,或者机器宕机),产品经理可能会选择从窗户上跳下去,没机会摘牌,导致了死锁饥饿,让这位优秀的工程师成了一位大闲人,造成严重的资源浪费。同时还需要注意这个 owner_id,它代表锁是谁加的 —— 产品经理的工号。以免你的锁不小心被别人摘掉了。释放锁时要匹配这个 owner_id,匹配成功了才能释放锁。这个 owner_id 通常是一个随机数,存放在 ThreadLocal 变量里(栈变量)。官方其实并不推荐这种方式,因为它在集群模式下会产生锁丢失的问题 —— 在主从发生切换的时候。官方推荐的分布式锁叫 RedLock,作者认为这个算法较为安全,推荐我们使用。不过我们一直还使用上面最简单的分布式锁。为什么我们不去使用 RedLock 呢,因为它的运维成本会高一些,需要 3 台以上独立的 Redis 实例,用起来要繁琐一些。另外,Redis 集群发生主从切换的概率也并不高,即使发生了主从切换出现锁丢失的概率也很低,因为主从切换往往都有一个过程,这个过程的时间通常会超过锁的过期时间,也就不会发生锁的异常丢失。还有呢就是分布式锁遇到锁冲突的机会也不多,这正如一个公司里明星程序员也比较有限一样,总是遇到锁排队那说明结构上需要优化。

    五:定时任务

    分布式定时任务有多种实现方式,最常见的一种是 master-workers 模型。
    master 负责管理时间,到点了就将任务消息仍到消息中间件里,然后worker们负责监听这些消息队列来消费消息。
    著名的 Python 定时任务框架 Celery 就是这么干的。但是 Celery 有一个问题,那就是 master 是单点的,如果这个 master 挂了,整个定时任务系统就停止工作了。
    在这里插入图片描述

    另一种实现方式是 multi-master 模型。这个模型什么意思呢,就类似于 Java 里面的 Quartz 框架,采用数据库锁来控制任务并发。
    会有多个进程,每个进程都会管理时间,时间到了就使用数据库锁来争抢任务执行权,抢到的进程就获得了任务执行的机会,然后就开始执行任务,这样就解决了 master 的单点问题。

    这种模型有一个缺点,那就是会造成竞争浪费问题,不过通常大多数业务系统的定时任务并没有那么多,所以这种竞争浪费并不严重。
    还有一个问题它依赖于分布式机器时间的一致性,如果多个机器上时间不一致就会造成任务被多次执行,这可以通过增加数据库锁的时间来缓解。
    在这里插入图片描述
    现在有了 Redis 分布式锁,那么我们就可以在 Redis 之上实现一个简单的定时任务框架。

    #注册定时任务
    hset tasks name trigger_rule
    #获取定时任务列表
    hgetall tasks
    # 争抢任务
    set lock:$(name) true nx ex=5
    # 任务列表变空
    # 轮询版本号,有变化就重新加载任务列表,重新调度时间有变化的任务
    set tasks_version $new_version
    get tasks_version
    

    六、频率控制

    项目的社区功能里,不可避免的总是会遇到垃圾内容,一觉醒来你会发现首页突然会被某些恶意的帖子和广告刷屏了,如果不采取适当的机制来控制就会导致用户体验受到严重的影响
    控制广告垃圾贴的策略很多,高级一点的可以通过AI,最简单的方式是通过关键词扫描,还有比较常用的一种方式是频率控制,限制单个用户内容的生产速度,不通等级的用户会有不同的频率控制参数
    频率控制就可以使用redis来实现,我们将用户的行为理解为一个时间序列,我们要保证在一定的时间内限制单个用户的时间序列的长度,超过这个长度就禁止用户的行为,它可以是用redis的zset(有序集合,zset详解)来实现
    在这里插入图片描述
    图中绿色的部门就是我们要保留的一个时间段的时间序列信息,灰色的段会被砍掉。统计绿色段中时间序列记录的个数就知道是否超过了频率的阈值。

    下面的代码控制用户的ugc行为为每小时最对N次
    hist_key:"ugc:${user_id}"
    with redis.pipeline() as pipe:
    # 记录当前的行为
    	pipe.zadd(hist_key,ts,uuid)
    	#保留1小时内的行为序列
    	pipe.zremrangebyscore(hist_key, 0, now_ts -3600)
    	# 获取这1小时的行为数量
    	pipe.zcard(hist_key)
    	# 设置过期时间,节约内存
    	pipe.expire(hist_key, 3600)
    	# 批量执行
    	_ , _ , count, _ =pipe.exec()
    	return count > N
    	
    

    七、服务发现

    如果想要技术成熟度再高一些,有的企业会有服务发现的基础设施。通常我们都会选用zookeeper、etcd,consul等分布式配置数据库来作为服务列表的存储
    它们有非常及时的通知机制来通知服务消费者服务列表发生了变更。那我们该如何使用 Redis 来做服务发现呢?
    在这里插入图片描述
    这里我们要再次使用 zset 数据结构,我们使用 zset 来保存单个服务列表。多个服务列表就使用多个 zset 来存储。
    zset 的 value 和 score 分别存储服务的地址和心跳的时间。服务提供者需要使用心跳来汇报自己的存活,每隔几秒调用一次 zadd。服务提供者停止服务时,使用 zrem 来移除自己。

    zadd service_key heartbeat_ts addr
    zrem service_key addr
    

    这样还不够,因为服务有可能是异常终止,根本没机会执行钩子,所以需要使用一个额外的线程来清理服务列表中的过期项

    zremrangebyscore service_key 0 now_ts -30 # 30s都没来心跳
    

    接下来还有一个重要的问题是如何通知消费者服务列表发生了变更,这里我们同样使用版本号轮询机制,当服务列表变更时,递增版本号。消费者通过轮询版本号的变化来重加载服务列表

    if zadd() >0 || zrem() >0 ||zremrangebuscore() >0:
    		incr service_version_key
    

    但是还有一个问题,如果消费者依赖了很多的服务列表,那么它就需要轮询很多的版本号,这样的IO效率会比较低下。

    这是我们可以再增加一个全局版本号,在任意的服务类表版本号发生变化时,递增全局版本号
    这样在正常情况下消费者只需要轮询全局版本号就可以了。当全局版本号发生变更时再挨个对依赖的服务类表的子版本号,然后加载有变更的服务列表
    在这里插入图片描述

    八、位图

    项目里需要做一个球队成员的签到系统,当用户量比较少的时候,设计上比较简单,就是将用户的签到状态用redis的hash结构来存储,签到一次就再hash结构里记录一条,签到有三种状态:未签到,已签到和部签到,分别是0,1,2三个整数值

    hset sign:$(user_id) 2019-08-11 1
    hset sign:$(user_id) 2019-08-12 0
    hset sign:$(user_id) 2019-08-14 2
    
    

    这个其实非常浪费用户空间,后来想做全部用户的签到,技术leader指出,这时候的再用hash就有问题了,他讲到当用户过千万的时候,内存可能会飚到 30G+,我们线上实例通常过了 20G 就开始报警,30G 已经属于严重超标了。
    这时候我们就开始着手解决这个问题,去优化存储。我们选择使用位图来记录签到信息,一个签到状态需要两个位来记录,一个月的存储空间只需要 8 个字节。这样就可以使用一个很短的字符串来存储用户一个月的签到记录。

    在这里插入图片描述
    但是位图也有一个缺点,它的底层是字符串,字符串是连续存储空间,位图会自动扩展,比如一个很大的位图 8m 个位,只有最后一个位是 1,其它位都是零,这也会占用1m 的存储空间,这样的浪费非常严重。
    所以呢就有了咆哮位图这个数据结构,它对大位图进行了分段存储,全位零的段可以不用存。
    另外还对每个段设计了稀疏存储结构,如果这个段上置 1 的位不多,可以只存储它们的偏移量整数。这样位图的存储空间就得到了非常显著的压缩。

    九、 模糊计数

    上面提到的签到系统,如果产品经理需要知道这个签到的日活月活怎么办呢?
    通常我们会直接甩锅——请找数据部门。
    但是数据部门的数据往往不是很实时,经常前一天的数据需要第二天才能跑出来,离线计算是通常是定时的一天一次。那如何实现一个实时的活跃计数?
    最简单的方案就是在 Redis 里面维护一个 set 集合,来一个用户,就 sadd 一下,最终集合的大小就是我们需要的 UV 数字。
    但是这个空间浪费严重怎么办?这时候就需要使用redis提供的HyperLogLog模糊计数功能,它是一种概率计数,有一定的误差,大约是0.81%。
    但是空间占用很小,其底层是一个位图,它最多只会占用12k的存储空间,而且在计数值比较小的时候,位图使用稀疏存储,空间占用就更小了。

    #记录用户
    pfadd sign_uv_${day} user_id
    #获取记录数量
    p count sign_uv_${day}
    
    

    微信公众号文章的阅读数可以使用它,网页的 UV 统计它都可以完成。但是如果产品经理非常在乎数字的准确性,比如某个统计需求和金钱直接挂钩,那么你可以考虑一下前面提到的咆哮位图。

    它使用起来会复杂一些,需要提前将用户 ID 进行整数序列化。Redis 没有原生提供咆哮位图的功能,但是有一个开源的 Redis Module 可以拿来即用。

    十、布隆过滤器

    如果系统即将会有大量的新用户涌入时,布隆过滤器就会非常有价值,可以显著降低缓存的穿透率,降低数据库的压力
    这个新用户的涌入不一定是业务系统的大规模铺开,也可能是因为来自外部的缓存穿透攻击

    def get_user_state(user_id):
    		state = cache.get(user_id)
    		if not state:
    			state = db.get(user_id) or{}
    			cache.set(user_id,state)
    		return state
    def save_user_state(user_id,state):
    		cache.set(user_id,state)
    		db.set_async(user_id,state)
    

    比如就上面这个业务系统的用户状态查询接口代码,现在一个新用户过来,会先去缓存里查询有没有这个用户的状态数据
    因为是新用户,所以肯定缓存里没有,然后它就要去数据库里查,结过数据库也没有,如果这样的新用户大批量瞬间涌入,那么可以遇见数据库的压力会比较大,会存在大量的空查询
    我们非常希望redis里面有这样一个set,它存放了所有的用户id,这样通过查询这个set集合就知道是不是新用户来了
    当用户量非常庞大的时候,维护这样的一个集合需要的存储空间是很大的
    这时候就可以使用布隆过滤器,它相当于一个set,但是又不同于set,它需要的存储空间要小的多
    比如存储一个用户id需要64个字节,而布隆过滤器存储一个用户ID只需要1个字节多点,其实它存的不是用户id,而是用户id的指纹,所以会存在一定的小概率误判,它是一个具备模糊过滤能力的容器
    在这里插入图片描述

    当它说用户 id 不在容器中时,那么就肯定不在。当它说用户 id 在容器里时,99% 的概率下它是正确的,还有 1% 的概率它产生了误判。

    不过在这个案例中,这个误判并不会产生问题,误判的代价只是缓存穿透而已。
    相当于有 1% 的新用户没有得到布隆过滤器的保护直接穿透到数据库查询,而剩下的 99% 的新用户都可以被布隆过滤器有效的挡住,避免了缓存穿透
    在这里插入图片描述
    布隆过滤器的原理有一个很好的比喻,那就是在冬天一片白雪覆盖的地面上,如果你从上面走过,就会留下你的脚印。如果地面上有你的脚印,那么就可以大概率断定你来过这个地方,但是也不一定,也许别人的鞋正好和你穿的一模一样。可是如果地面上没有你的脚印,那么就可以 100% 断定你没来过这个地方

    说明:该文写到一半时,偶然看到了下面简书作者的这篇文章,原文写的很好,跟我的项目中的一些业务逻辑很吻合,故将其引用过来,如有疑惑,请去原文阅读Java老王
    展开全文
  • redis 数据类型与使用场景

    千次阅读 2019-02-21 11:39:08
    incr / decr使用场景 :  1. 把某件商品数量放 jedis.set("product", ""+100);  2. 秒杀购买这件商品 Long incr = jedis.decr("product"); 减1后, 然后获得产品余量>0代表还没售完;  然后把当前用户购买...
  • 从本质上讲,大数据对于商业营销的价值是为了组织更好的产品或服务的流通,以最快的速度、最高效的方式解决大多数人的需求,并实现稳定的收益。  其实,大数据其实已经在为商业的发展提供实际的应用,总结了大数据...
  • 9)使用场景: 1、资源优化场景。 2、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。 3、性能和安全要求的场景。 4、通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型...
  • [数据库] 一文搞懂case when所有使用场景

    万次阅读 多人点赞 2019-02-01 16:44:44
    前几天,为了给产品分析当前用户数据结构,写sql的时候使用到了case when,今天来总结一下casewhen的使用方法,以此为戒,感觉写的不好请拍砖,感觉写的还可以,给哥们点个赞,或者回复一下,让我意识到我不是一个人...
  • 文章出自:安卓进阶学习指南 主要贡献者: Cloud9527 Alex_赵 Struggle shixinzhang ...成员内部类的使用场景 静态内部类的使用场景 匿名内部类的使用场景 局部内部类 内存泄漏 总结 ...
  • 一、使用场景和业务需求描述

    千次阅读 2019-09-24 05:04:42
     请问下 ,你们的产品很全,根据我们的业务 会使用到你们那个软件产品 给我的回答:  主要要用到的就是资源服务,用于获取设备资源,还有视频应用,获取预览url。  历史版本里的1.2.0  http使用的是36100,...
  • IBM-MQ原理及使用场景

    万次阅读 2017-11-30 09:49:13
    在MQ家族产品中,MQ Event Broker是专门用于使用发布/订阅技术进行数据通讯的产品,它支持基于队列和直接基于TCP/IP两种方式的发布和订阅。  4) 群集(Cluster):为了简化点对点通讯模式中的系统配置,MQ提供...
  • Redis实战经验及使用场景

    千次阅读 2016-08-24 20:42:04
    发现一种情况,开发在沟通后端资源设计的时候,常常因为习惯使用和错误了解产品定位等原因,而忽视了对真实使用用户的评估。也许这是一份历史数据,只有最近一天的数据才有人进行访问,而把历史数据的容量和最近一天...
  • 使用场景 1.异步处理 场景说明:用户注册后,需要发注册邮件和注册短信 引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理  由此可以看出,引入消息队列后,用户的响应时间就等于写入数据库的时...
  • 什么是物联网?看到这个问题,相信很多人都是蒙圈状态,虽然物联网已经10周年了,但是经过10年的发展,大多数的人都无法说不清楚物联网,说不清物联网到底是什么,更不用说看清物联网的商业模式,自然也就无法界定谁...
  • EOS Governor是对EOS Server进行管理和配置的管理控制台,本文针对Governor各配置项以及使用场景做了比较多的描述,欢迎参考!
  • 此文章对开放数据接口 API 进行了功能介绍、使用场景介绍以及调用方法的说明,供用户在使用数据接口时参考之用。 在给大家分享的一系列软件开发视频课程中,以及在我们的社区微信群聊天中,都积极地鼓励大家开发自己...
  • redis的类型、原理及使用场景

    万次阅读 2016-12-17 20:00:22
    1. MySQL+Memcached架构...Memcached采用客户端-服务器的架构,客户端和服务器端的通讯使用自定义的协议标准,只要满足协议格式要求,客户端Library可以用任何语言实现。 Memcached服务器使用基于Slab的内存
  • 如果你不能回到业务场景,回到用户使用产品场景,不能从用户使用场景的角度来回答、沟通问题,那么很多时候会造成沟通的不顺畅,以及产品推进受阻的现象。 2.回到原点思考, 我们经常讲,产品经理在具体工作的...
  • CDN内容分发网络,那么具体是什么意思呢?又有哪些具体的服务提供者? 1. CDN解释 摘自 解释 维基百科 内容分发网络(Content delivery network或Content distribution network,缩写:CDN...
  • 场景测试

    千次阅读 2009-07-10 10:46:00
    什么场景? 场景就是假设的故事,用来帮助人们理解一个复杂的问题或者系统。 一个完美的场景测试有几个特征: 1. 基于一个用户怎么使用软件的故事,包括用户的动机 2. 故事具有感染力,有影响力的干系人会促使这个...
  • 分账系统是一个基于虚拟账户和订单支付体系的开放平台,能够为 B2B2C/O2O 平台型商户的各类业务场景提供虚拟账户、支付产品和资金管理服务。 另外," 分账系统 " 独立于电商平台系统,隐藏在平台后端,为...
  • 设计模式在实际场景中的使用

    千次阅读 2018-05-23 15:17:58
    设计模式一、什么是设计模式?设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问...
  • 一、MQ简介及特点 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接...队列的使用除去了接收
  • MLSQL Stack 应用场景示例

    千次阅读 2019-04-27 15:37:11
    前言 MLSQL Stack 都有哪些应用场景呢?毕竟现在是个场景为王的时代。其实MLSQL Stack有无限的可能性等待大家挖掘。下面我们提一些已经在应用的。 数据同步组件 ...什么意思呢?就是根据业务需求,用M...
  • 国内外三个不同领域巨头分享的Redis实战经验及使用场景 发表于2013-10-07 09:03| 13637次阅读| 来源CSDN| 20 条评论| 作者仲浩 云计算大数据NoSQLRedis新浪微博PinterestViacom 摘要:随着数据...
  • 区块链是什么意思

    千次阅读 2018-05-31 10:52:02
    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型...区块链是一串使用密码学方法相关联产生的数据块,每一个数据块中包含了一次比特币网络交易的信息,用于验证其信息的有效性(防伪)和...
  • 一、MQ简介及特点  MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接...队列的使用除去了接收和
  • Redis 简介 ...Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。 Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存...
  • 微软于2017年2月正式发布了Microsoft Planner 功能,用户可以通过电脑、Mac或者...场景描述: 一个项目团队可以通过Microsoft Planner快速构建团队协作模式,保证团队人员能随时随地在任何设备上跟踪团队的进度,掌...
  • 产品说明、场景演示都越来越多采用视频的形式。而线上教育、原创视频等对于自有版权的视频,想限制其传播和播放也是很多业内人士的基本诉求。而常用的一机一码,是应对这个问题比较有效的办法。但是视频加密系统中常...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 56,810
精华内容 22,724
关键字:

产品使用场景是什么意思