使用 ETS 与 Mnesia 处理分布式数据
了解 ETS 的内存分布式表,以及 Mnesia 提供的轻量级分布式数据库能力。
使用 ETS 与 Mnesia 处理分布式数据 是 CoddyKit 上的免费 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Why Distributed Data?
In large-scale Erlang systems, data often needs to be shared and synchronized across multiple nodes. This is crucial for building fault-tolerant and scalable applications.
Imagine a chat application where user sessions or message queues need to be accessible even if one server fails. Distributed data stores make this possible by allowing data to live beyond a single process or node.
Erlang Term Storage (ETS)
ETS stands for Erlang Term Storage. It's a powerful, built-in in-memory key-value store. Think of it as a super-fast hash table directly integrated into the Erlang runtime.
- Extremely fast for read/write operations.
- Can store any Erlang term (integers, atoms, lists, tuples, PIDs, etc.).
- Process-safe: multiple processes can access the same table concurrently.
Exploring ETS Table Types
ETS offers different table types, each with unique properties:
set: The default. Each key can only have one value. Like a dictionary.ordered_set: Similar toset, but keys are kept sorted. Slower writes, faster range lookups.bag: Allows multiple objects with the same key.duplicate_bag: Allows multiple objects with the same key AND value.
Choosing the right type depends on your data's structure and access patterns.
Basic ETS Operations
Let's see how to create an ETS table and perform basic operations like inserting and looking up data. We'll use a set table for simplicity.
-module(ets_example).
-export([run/0, add_user/2, get_user/1, cleanup/0]).
% Function to run the example sequence
run() ->
io:format("--- ETS Example Start ---~n"),
% Create a named public set table
ets:new(users_table, [set, public, named_table]),
io:format("Table 'users_table' created.~n"),
add_user(1, "Alice"),
add_user(2, "Bob"),
add_user(1, "Alicia"), % This will update Alice to Alicia
get_user(1),
get_user(2),
get_user(3), % User 3 doesn't exist
cleanup(),
io:format("--- ETS Example End ---~n").
add_user(Id, Name) ->
ets:insert(users_table, {Id, Name}),
io:format("Inserted/updated user {~p, ~p}~n", [Id, Name]).
get_user(Id) ->
case ets:lookup(users_table, Id) of
[{Id, Name}] ->
io:format("Lookup result for ~p: {~p, ~p}~n", [Id, Name]);
[] ->
io:format("User ~p not found in table.~n", [Id])
end.
cleanup() ->
ets:delete(users_table),
io:format("Table 'users_table' deleted.~n").ETS: Local Storage Only
While ETS is incredibly fast and concurrent, it's important to remember a key limitation: ETS tables are local to the Erlang node where they are created.
- Data in an ETS table on
node_Ais not automatically available onnode_B. - To share ETS data across nodes, you'd need to implement custom replication or remote access mechanisms, often using message passing or RPC.
This is where Mnesia comes in to simplify distributed data management.
Mnesia: Erlang's Distributed DB
Mnesia is a powerful, distributed, fault-tolerant, real-time database management system built into Erlang/OTP. It leverages ETS and DETS (Disk Erlang Term Storage) for its storage.
Mnesia simplifies the challenges of managing data across multiple Erlang nodes, providing transactional guarantees and automatic replication, making it ideal for robust distributed applications.
Mnesia Setup & Schema
Before using Mnesia, you need to start it and define your data schema. The schema describes your tables and their properties (e.g., what node hosts which copy).
mnesia:start(): Initializes the Mnesia system.mnesia:create_schema([node()]): Creates the Mnesia directory and schema on the specified nodes. This is typically a one-time setup per cluster.mnesia:create_table(Name, Props): Defines a new table with its attributes and storage type.
Mnesia Transactions
Mnesia operations are typically performed within transactions to ensure atomicity, consistency, isolation, and durability (ACID properties). This means all operations within a transaction either succeed or fail together.
Here's how to create a table and interact with it using transactions:
-module(mnesia_example).
-export([init_mnesia/0, add_product/2, get_product/1, cleanup/0]).
% Define a record for our product data
-record(product, {id, name}).
init_mnesia() ->
io:format("--- Mnesia Init Start ---~n"),
% Start Mnesia
mnesia:start(),
io:format("Mnesia started.~n"),
% Uncomment and run 'mnesia_example:create_schema().' once for a new Mnesia setup:
% mnesia:create_schema([node()]),
% io:format("Mnesia schema created.~n"),
% Create product table with disc_copies on this node
% Uncomment to delete an existing table before creating a new one:
% mnesia:delete_table(product),
TableProps = [{disc_copies, [node()]}, {attributes, record_info(fields, product)}],
case mnesia:create_table(product, TableProps) of
{atomic, ok} -> io:format("Table 'product' created.~n");
{aborted, {already_exists, product}} -> io:format("Table 'product' already exists.~n");
Other -> io:format("Error creating table: ~p~n", [Other])
end,
io:format("--- Mnesia Init End ---~n").
add_product(Id, Name) ->
Product = #product{id = Id, name = Name},
F = fun() -> mnesia:write(Product) end,
case mnesia:transaction(F) of
{atomic, ok} -> io:format("Added product {~p, ~p}~n", [Id, Name]);
{aborted, Reason} -> io:format("Failed to add product: ~p~n", [Reason])
end.
get_product(Id) ->
F = fun() -> mnesia:read({product, Id}) end,
case mnesia:transaction(F) of
{atomic, [ProductRecord]} ->
io:format("Found product ~p: {~p, ~p}~n", [Id, ProductRecord#product.name]);
{atomic, []} ->
io:format("Product ~p not found.~n", [Id]);
{aborted, Reason} ->
io:format("Failed to get product: ~p~n", [Reason])
end.
cleanup() ->
io:format("--- Mnesia Cleanup Start ---~n"),
mnesia:stop(),
io:format("Mnesia stopped.~n"),
io:format("--- Mnesia Cleanup End ---~n").Mnesia Data Replication
Mnesia achieves distribution and fault tolerance through data replication. When creating a table, you specify where its copies should reside:
disc_copies: Data is stored on disk and in RAM on the specified nodes. Best for persistence and fault tolerance.ram_copies: Data is stored only in RAM on the specified nodes. Faster access but data is lost on node crash unless adisc_copiesis also present elsewhere.disc_only_copies: Data is stored only on disk. Slowest access but lowest RAM footprint.
Mnesia automatically handles replication and synchronization across these copies, ensuring data consistency.
Quick Check: ETS vs Mnesia
Both ETS and Mnesia are powerful tools for managing data in Erlang, but they serve different purposes. Select all statements that correctly describe the key differences or characteristics.
Recap: Distributed Data Tools
In this lesson, we explored two essential tools for managing data in Erlang: ETS and Mnesia.
- ETS is a super-fast, in-memory key-value store, excellent for local caches and lookup tables. Remember, it's local to a node.
- Mnesia is Erlang's built-in distributed, fault-tolerant database. It offers transactional safety, schema definition, and automatic data replication across nodes, built upon ETS.
Understanding when to use each is key to building resilient and scalable Erlang applications.
常见问题解答
「使用 ETS 与 Mnesia 处理分布式数据」课时是免费的吗?
是的 — 「使用 ETS 与 Mnesia 处理分布式数据」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 课程的其余内容,请升级到 CoddyKit PRO。 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 课程共包含 4 节课。
「使用 ETS 与 Mnesia 处理分布式数据」这节课中我会学到什么?
了解 ETS 的内存分布式表,以及 Mnesia 提供的轻量级分布式数据库能力。 你通过在浏览器中直接运行的动手代码来练习 Erlang OTP: Distributed & Fault-Tolerant Systems Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 ETS 与 Mnesia 处理分布式数据」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 课中编写并运行代码吗?
能。每节 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 处理网络分区
- 使用 ETS 与 Mnesia 处理分布式数据
- 可扩展性与弹性设计
- 跨节点负载均衡与故障转移