elixir 高可用系列(一) Agent
概述
elixir 本身是一种 immutable 的语言,默认情况下,进程间是不共享任何状态的,进程之间通过消息来交互。
而 Agent 则封装了一种进程间共享状态的方式,通过这种方式,不用显式的写 send/receieve 的代码,就能方便的在进程之间共享状态。
使用方法
不用 Agent 来管理状态
首先,看一个在不用 Agent 的情况下,如何获取进程状态的例子。
defmodule WithoutAgent do
def start do
Map.new()
end
def get(map, key) do
if Map.has_key?(map, key) do
Map.get(map, key)
else
nil
end
end
def put(map, key, val) do
Map.put(map, key, val)
end
def delete(map, key) do
Map.delete(map, key)
end
end
测试 WithoutAgent 的使用:
iex> m = WithoutAgent.start
%{}
iex> WithoutAgent.get(m, "map-key")
nil
iex> m = WithoutAgent.put(m, "map-key", "map-val")
%{"map-key" => "map-val"}
iex> WithoutAgent.get(m, "map-key")
"map-val"
iex> m = WithoutAgent.delete(m, "map-key")
%{}
iex> m = WithoutAgent.get(m, "map-key")
nil
从上面的使用可以看出,为了使用 WithoutAgent 中的状态(一个 map),外部还必须要自己管理 WithoutAgent 的返回的状态 m,
通过 WithoutAgent 来改变状态时,每次都要将当前状态 m 作为一个参数传给 WithoutAgent。
只有一个进程使用 WithoutAgent 时,上述方式没有什么问题,当有多个进程使用 WithoutAgent,每个进程持有的状态 m 很难保持一致。
使用 Agent 来管理状态
elixir 中的 Agent 其实并不是 elixir 发明的新东西,而是封装了 erlang OTP 中现有的 ETS (Erlang Term Storage)
使用 Agent 来重新实现上面的例子:
defmodule WithAgent do
def start do
Agent.start_link(fn -> Map.new end, name: __MODULE__)
end
def get(key) do
Agent.get(__MODULE__, fn map ->
if Map.has_key?(map, key) do
Map.get(map, key)
else
nil
end
end)
end
def put(key, val) do
Agent.update(__MODULE__, &Map.put(&1, key, val))
end
def delete(key) do
Agent.get_and_update(__MODULE__, fn map ->
if Map.has_key?(map, key) do
Map.pop(map, key)
else
nil
end
end)
end
end
测试 WithAgent 的使用:
iex> WithAgent.start
{:ok, #PID<0.108.0>}
iex> WithAgent.get("map-key")
nil
iex> WithAgent.put("map-key", "map-val")
:ok
iex> WithAgent.get("map-key")
"map-val"
iex> WithAgent.delete("map-key")
"map-val"
iex> WithAgent.get("map-key")
nil
从上面的使用中可以看出,使用了 Agent 之后,使用方完全不用自己管理 WithAgent 的状态,只要操作状态即可。
这样,多个进程同时使用 WithAgent 时,也不用管状态冲突的事情,状态如果有冲突也是在 WithAgent 中自己管理。
总结
总的来说,Agent 就是状态的简单的封装,方便进程间状态的共享。
此外,除了上面用的方法,Agent 中的所有方法参照:Agent
elixir 高可用系列(一) Agent的更多相关文章
- elixir 高可用系列 - 目录
1. elixir 高可用系列(一) Agent 2. elixir 高可用系列(二) GenServer 3. elixir 高可用系列(三) GenEvent 4. elixir 高可用系列(四) ...
- elixir 高可用系列(五) Supervisor
概述 OTP 平台的容错性高,是因为它提供了机制来监控所有 processes 的状态,如果有进程出现异常, 不仅可以及时检测到错误,还可以对 processes 进行重启等操作. 有了 superv ...
- elixir 高可用系列(四) Task
概述 之前学习的 Agent,GenSever以及GenEvent,都是用来管理状态或者处理消息的. 但是在很多时候,我们需要的是执行某个任务,这时如果使用 GenSever 或者 GenEvent, ...
- elixir 高可用系列(三) GenEvent
概述 GenEvent 是事件处理的通用部分的抽象. 通过 GenEvent ,我们给已有的服务 动态 的添加 事件处理. GenEevent 和 GenServer 的区别 之前已经介绍了 GenS ...
- elixir 高可用系列(二) GenServer
概述 如果我们需要管理多个进程,那么,就需要一个专门的 server 来集中监控和控制这些进程的状态,启停等. OTP 平台中的 GenServer 就是对这个 server 通用部分的抽象. 利用 ...
- (5.8)mysql高可用系列——MySQL中的GTID复制(实践篇)
一.基于GTID的异步复制(一主一从)无数据/少数据搭建 二.基于GTID的无损半同步复制(一主一从)(mysql5.7)基于大数据量的初始化 正文: [0]概念 [0.5]GTID 复制(mysql ...
- (5.15)mysql高可用系列——MHA实践
关键词:MHA,mysql mha [1]需求 采用mysql技术,实现MHA高可用主从环境,预计未来数据量几百G MHA概念参考:MYSQL高可用技术概述 [2]环境技术架构 [2.1]MHA简介 ...
- 高可用系列之Nginx
1.1Keepalived高可用软件 Keepalived起初是专为LVS设计的,专门用来监控LVS集群系统中各个服务节点的状态,后来又加入了VRRP的功能,因此除了配合LVS服务外,也可以作为其他服 ...
- keepalived高可用系列~ keepalived+proxysql
一 简介:介绍下高可用通用的方案 二 目的:一个中间件提供服务,故障后,另一个中间件提供服务 三 手段: 应用keepalived的vrrp_scripts服务 四 具体配置 global_defs ...
随机推荐
- vagrant系列教程(三):vagrant搭建的php7环境(转)
原文:http://blog.csdn.net/hel12he/article/details/51107236 前面已经把vagrant的基础知识已经基本过了一遍 了,相信只要按着教程来,你已经搭建 ...
- mysql之触发器入门
触发器语法: CREATE TRIGGER <触发器名称> --触发器必须有名字,最多64个字符,可能后面会附有分隔符.它和MySQL中其他对象的命名方式基本相象.{ BEFORE | ...
- XidianOJ 1183 Water Problem: Items divided
题目描述 Youyouyouyou is very interested in math, one day, an idea came into his mind that how many ways ...
- 开发BBS论坛
一.涉及表结构 web\model.py(首选需要注意表结构的设计,如果表结构设计出来了,软件的架构也就基本出来了) #!/usr/bin/env python # _*_ coding:utf- _ ...
- html如何绑定radio控件和label控件
只要指定label的"for"属性到radio的id就行,或者用label标签包围住radio. 第一种方式: <input type="radio" i ...
- bash脚本编程之二 条件判断and 逻辑运算
1.条件测试结构 1) if/then结构: 判断命令列表的退出码是否为0,0为成功. 如果if和then在条件判断的同一行上的话, 必须使用分号来结束if表达式: if和then都是关键字. 关键字 ...
- jQuery自动补全
方法一: jquery-autocomplete配置: <script type="text/javascript" src="/js/jquery-1.4.2.m ...
- 创建 XMLHttpRequest 对象
var _createHttpRequest = function () { var obj; if (window.XMLHttpRequest) obj = new XMLHttpRequest( ...
- 自定义UIPageControl,可设置任意图片image。
[self.pageControl setValue:[UIImage imageNamed:@"选中图片名称"] forKeyPath:@"_currentPageIm ...
- System.IO中的File、FileInfo、Directory与DirectoryInfo类(实例讲解)
一.建立的文件夹(对这些文件进行以上四个类的操作): 父目录: 父目录的子目录以及父目录下的文件: 子目录下的文件: 二.效果图 三.代码实现 using System; using System.I ...