计算机中的幂等性「建议收藏」

[原创链接:http://www.smithfox.com/?e=16转载请保留此声明,谢谢]绝大部分网络上对幂等性的解释类似于:”幂等性是指重复使用同样的参数调用同一方法时总能获得同样的结果。比如对同一资源的GET请求访问结果都是一样的。”我认为这种解释是非常错误的,幂等性强调的是外界通过接口对系统内部的影响,外界怎么看系统和幂等性没有关系.就上面这种解释,

大家好,又见面了,我是你们的朋友全栈君。

[原创链接: http://www.smithfox.com/?e=16 转载请保留此声明, 谢谢]

绝大部分网络上对幂等性的解释类似于:

幂等性是指重复使用同样的参数调用同一方法时总能获得同样的结果。比如对同一资源的GET请求访问结果都是一样的。

我认为这种解释是非常错误的, 幂等性强调的是外界通过接口对系统内部的影响, 外界怎么看系统和幂等性没有关系. 就上面这种解释, System.getCPULoad(), 这两次调用返回能一样吗? 但因为是只读接口, 对系统内部状态没有影响, 所以这个函数还是幂等性的.

首先了解一下什么是幂等性,如果你没有兴趣可以直接跳过这段代数概念解释 :)

幂等(idempotence)是来自于高等代数中的概念。

定义如下(加入了自己理解):

单目运算, x为某集合内的任意数, f为运算子如果满足f(x)=f(f(x)), 那么我们称f运算为具有幂等性(idempotent)

比如在实数集中,绝对值运算就是一个例子: abs(a)=abs(abs(a))

双目运算,x为某集合内的任意数, f为运算子如果满足f(x,x)=x, f运算的前提是两个参数都同为x, 那么我们也称f运算为具有幂等性

比如在实数集中,求两个数的最大值的函数: max(x,x) = x, 还有布尔代数中,逻辑运算 “与”, “或” 也都是幂等运算, 因为他们符合AND(0,0) = 0, AND(1,1) = 1, OR(0,0) = 0, OR(1,1) = 1

在将幂等性应用到软件开发中,需要一些更深的理解. 我的理解如下:

数学处理的是运算和数值, 程序开发中往往处理的是对象和函数. 但是我们不能简单地理解为数学幂等中的运算就是函数,而数值就是对象!!

比如有Person对象有两个属性weight和age,但是所有的function只能对其中一个属性操作. 所以从这个层面我们可以理解为: 函数只对该函数所操作的对象某个属性具有幂等性, 而不是说对整个对象有运算幂等性.

[java] 
view plain
copy

  1. Person {  
  2.  private int weight;  
  3.  private int age;  
  4.  //是幂等函数  
  5.  public void setAge(int v){  
  6.      this.age = v;   
  7.  }  
  8.  //不是幂等函数  
  9.  public void increaseAge(){  
  10.      this.age++;  
  11.  }   
  12.  //是幂等函数  
  13.  public void setWeight(int v){  
  14.      this.weight=v+10;//故意加10斤!!  
  15.  }  
  16. }  

还有一点必须要澄清的是: 幂等性所表达的概念关注的是数学层面的运算和数值, 并没有提及到数值的安全性问题.

比如上面的Person的setAge函数, 有两种case不是幂等性所关心的, 但程序开发却又必须要关心的:

1. 两个线程同时调用

2. 因为age从业务上讲不可能递减, 如果前一次调用设置是30岁, 后一次调用变成了10岁或是更离谱的 -1 岁

所以RESTful设计中将幂等性和安全性是作为两个不同的指标来衡量POST,PUT,GET,DELETE操作的:

重要方法 安全? 幂等?
GET
DELETE
PUT
POST

幂等性是系统的接口对外一种承诺(而不是实现), 承诺只要调用接口成功, 外部多次调用对系统的影响是一致的. 声明为幂等的接口会认为外部调用失败是常态, 并且失败之后必然会有重试.

就象cache有cache基本实现范式一样, 幂等也有自己的固定外部调用范式
cache实现范式:
[java] 
view plain
copy

  1. value getValue(key){  
  2.     value = getValueFromCache(key);  
  3.   
  4.     if( value == null ){  
  5.         value = readFromPersistence(key);  
  6.         saveValueIntoCache(key,value);  
  7.     }  
  8.   
  9.     return value;  
  10. }  
幂等外部调用范式
[java] 
view plain
copy

  1. client.age = 30;  
  2.   
  3. while(一些退出条件){  
  4.     try{  
  5.         if(socket.setPersonAge(person,client.age) == FAILED){  
  6.             int newAge = socket.getPersonAge();  
  7.             //处理冲突问题: 因为age只可能越来越大,所以将client的age更新为server端更大的age  
  8.             if(newAge>30){  
  9.             client.age = newAge;  
  10.             break;  
  11.         } else{  
  12.         <span style=“white-space: pre; “>   </span>//无法进行冲突解决,再次尝试  
  13.         }  
  14.         } else return;  
  15.     } catch(Exception){  
  16.         //发生网络异常, 再次尝试  
  17.     }  
  18. }  

幂等接口的内部实现需要有对内保护机制, 一般情况是用类似于乐观锁的版本机制.版本重点是体现时间的先后.

[原创链接: http://www.smithfox.com/?e=16 转载请保留此声明, 谢谢]

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/127517.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • uint16与int16的区别_golang int转string

    uint16与int16的区别_golang int转stringGolang中uint、int,int8,int16,int32,int64区别在第一次学习go语言时,对go语言的各种int类型充满疑惑,为什么会有int、int8、int16等等的类型呢?为什么不像java一样,只个int类型呢?直接上demotest.gopackagemainimport(“fmt””unsafe”)fun…

    2022年9月20日
    0
  • mysql decimal 实现_mysql decimal数据类型转换的实现示例

    mysql decimal 实现_mysql decimal数据类型转换的实现示例mysqldecimal数据类型转换的实现示例发布时间:2021-02-1408:40:00来源:亿速云阅读:85作者:小新小编给大家分享一下mysqldecimal数据类型转换的实现示例,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!最近在工作遇到数据库中存的数据类型是:decimal(14,4)遇到的问题是:当我使用python读取到内存中时,总是带着decimal…

    2022年7月17日
    14
  • python精彩编程200例-python趣味编程100例(99个)

    【实例简介】python如今很流行,AI的首选工具;python趣味编程100例(99个),学习编程不枯燥。【实例截图】【核心代码】python趣味编程100例(99个)└──python趣味编程100例(99个)├──JCP001.py├──JCP002.py├──JCP003.py├──JCP004.py├──JCP005.py├──JCP006.py├──JCP007.py├…

    2022年4月7日
    49
  • centos7 防火墙开放svn通过

    centos7 防火墙开放svn通过

    2022年3月8日
    42
  • 74款android开机动画,修改Android系统开机动画

    74款android开机动画,修改Android系统开机动画Android系统开机动画包括两部分:开机显示的ANDROID文字;ANDROID发光动画。这篇文章说的开机动画是第一种,下面开始正文!1.制作当前屏幕像素的图片(模拟器默认为320*480)使用PS制作一张320*480的图片,保存时选“保存为Web所用格式”,然后在弹开的窗口上,“预设”项选择“PNG-24”,保存为android_logo.png注:好像只支持png-24,其他格式生…

    2022年5月14日
    46
  • 小程序onLaunch事件的坑「建议收藏」

      记一个小程序踩过的坑小程序项目中app.js里面定义了globalData,即全局变量,里面定义了一个token字段需求是这样的,每次进入小程序的时候需要检验该token有没有,没有就请求后台获取token,由于我一开始将该检验函数A放在onLaunch事件里面,但是这个函数A是引入的其他js文件里面的,这时候我在这个js文件里面使用constapp=getApp()的时候发现获…

    2022年4月14日
    48

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号