概述

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

来源:http://blog.iotalabs.io/

elixir 高可用系列(一) Agent的更多相关文章

  1. elixir 高可用系列 - 目录

    1. elixir 高可用系列(一) Agent 2. elixir 高可用系列(二) GenServer 3. elixir 高可用系列(三) GenEvent 4. elixir 高可用系列(四) ...

  2. elixir 高可用系列(五) Supervisor

    概述 OTP 平台的容错性高,是因为它提供了机制来监控所有 processes 的状态,如果有进程出现异常, 不仅可以及时检测到错误,还可以对 processes 进行重启等操作. 有了 superv ...

  3. elixir 高可用系列(四) Task

    概述 之前学习的 Agent,GenSever以及GenEvent,都是用来管理状态或者处理消息的. 但是在很多时候,我们需要的是执行某个任务,这时如果使用 GenSever 或者 GenEvent, ...

  4. elixir 高可用系列(三) GenEvent

    概述 GenEvent 是事件处理的通用部分的抽象. 通过 GenEvent ,我们给已有的服务 动态 的添加 事件处理. GenEevent 和 GenServer 的区别 之前已经介绍了 GenS ...

  5. elixir 高可用系列(二) GenServer

    概述 如果我们需要管理多个进程,那么,就需要一个专门的 server 来集中监控和控制这些进程的状态,启停等. OTP 平台中的 GenServer 就是对这个 server 通用部分的抽象. 利用 ...

  6. (5.8)mysql高可用系列——MySQL中的GTID复制(实践篇)

    一.基于GTID的异步复制(一主一从)无数据/少数据搭建 二.基于GTID的无损半同步复制(一主一从)(mysql5.7)基于大数据量的初始化 正文: [0]概念 [0.5]GTID 复制(mysql ...

  7. (5.15)mysql高可用系列——MHA实践

    关键词:MHA,mysql mha [1]需求 采用mysql技术,实现MHA高可用主从环境,预计未来数据量几百G MHA概念参考:MYSQL高可用技术概述 [2]环境技术架构 [2.1]MHA简介 ...

  8. 高可用系列之Nginx

    1.1Keepalived高可用软件 Keepalived起初是专为LVS设计的,专门用来监控LVS集群系统中各个服务节点的状态,后来又加入了VRRP的功能,因此除了配合LVS服务外,也可以作为其他服 ...

  9. keepalived高可用系列~ keepalived+proxysql

    一 简介:介绍下高可用通用的方案 二 目的:一个中间件提供服务,故障后,另一个中间件提供服务 三 手段: 应用keepalived的vrrp_scripts服务 四 具体配置 global_defs ...

随机推荐

  1. Python 2.7_First_try_爬取阳光电影网_20161206

    之前看过用Scrapy 框架建立项目爬取 网页解析时候用的Xpath进行解析的网页元素 这次尝试用select方法匹配元素 1.入口爬取页面 http://www.ygdy8.com/index.ht ...

  2. Vc++ 控件用法总结之List Control

    1.新建对话框MFC,在对话框上放一个ListCtrl ID:IDC_PATH View:Report 2.为ListCtrl添加变量 右击->添加变量m_wndPath 3.找到OnInitD ...

  3. How to Shorten the Paper

    . Remember: you are writing for an expert. Cross out all that is trivial or routine. . Avoid repetit ...

  4. 转 A Week with Mozilla's Rust

    转自http://relistan.com/a-week-with-mozilla-rust/ A Week with Mozilla's Rust I want another systems la ...

  5. java基础十[包、Jar存档文件和部署](阅读Head First Java记录)

    将Java的class文件生成为可执行的Java应用程序.Java应用程序有三种:完全在本机执行的Jar(例如本机的GUI可执行程序):完全在服务器端远程执行的(例如浏览器来进行存取):介于两者之间的 ...

  6. Linux编程获取本地IP

    #include <stdio.h> #include <sys/types.h> #include <ifaddrs.h> #include <netine ...

  7. SQL性能优化(Oracle)

    首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录, ...

  8. java核心知识点学习----多线程并发之线程同步

    1.什么是线程同步? 多线程编程是很有趣的事情,它很容易出现"错误情况",这种情况不是由编码造成的,它是由系统的线程调度造成的,当使用多个线程来访问同一个数据时,很容易出现&quo ...

  9. [刘阳Java]_Java环境搭建_第2讲

    1.为什么搭建Java的环境 Java的程序语言不能独立在操作系统上运行 Java程序需要一个JVM(Java虚拟机)才能将程序员写好的Java程序运行在操作系统 Java程序的跨平台(Mac, Li ...

  10. 使用Memcached提高.NET应用程序的性能

    在应用程序运行的过程中总会有一些经常需要访问并且变化不频繁的数据,如果每次获取这些数据都需要从数据库或者外部文件系统中去读取,性能肯定会受到影响,所以通常的做法就是将这部分数据缓存起来,只要数据没有发 ...