Riak Core Guide 1

【信息科学与工程学】【数据中心】第三十五篇 云计算数据中心的学科知识04 编号学科(课程)核心知识点在云计算/云存储/云网络/云安全/云MaaS中的作用代表教材/资料/论文 + 数学方程式列表工业界应用D1421​云原生数据库:TiDB​HTAP(混合事务/分析处理)、分布式SQL、水平扩展、强一致(Raft)、自动故障恢复、与MySQL兼容、TiFlash列式引擎提供弹性扩展的分布式数据库;支撑高并发在线交易与实时分析教材:《TiDB in Action》PingCAP(2020) 论文:《TiDB: A Raft-based HTAP Database》(2017) 阅读详情

Learn Riak Core Step By Step


riak core 是 riak的主要组成部分,主要负责分布式的部分,虽然官方有自己的存储后端,但是我们也可以使用其他的后端存储。


Partitioning & Distributing Work

riak core 在每个节点上都是使用master/worker配置,这样作为一个工作单元来执行,riak core的worker为vnode worker, 在每个节点上由riak_core_sup生成,vnode worker对应的模块为riak_core_vnode。

如:

节点1:

Node: 'mfmn2@127.0.0.1', Process: <0.80.0>
[{registered_name,riak_core_vnode_sup},
 {current_function,{gen_server,loop,6}},
 {initial_call,{proc_lib,init_p,5}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[<0.148.0>,<0.152.0>,<0.154.0>,<0.155.0>,<0.153.0>,<0.150.0>,
         <0.151.0>,<0.149.0>,<0.140.0>,<0.144.0>,<0.146.0>,<0.147.0>,
         <0.145.0>,<0.142.0>,<0.143.0>,<0.141.0>,<0.136.0>,<0.138.0>,
         <0.139.0>,<0.137.0>,<0.77.0>,<0.135.0>]},
 {dictionary,[{'$ancestors',[riak_core_sup,<0.76.0>]},
              {'$initial_call',{supervisor_pre_r14b04,init,1}}]},
 {trap_exit,true},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.75.0>},
 {total_heap_size,3571},
 {heap_size,2584},
 {stack_size,9},
 {reductions,4359},
 {garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,10},
                      {minor_gcs,6}]},
 {suspending,[]}]

节点2:

Node: 'mfmn1@127.0.0.1', Process: <0.80.0>
[{registered_name,riak_core_vnode_sup},
 {current_function,{gen_server,loop,6}},
 {initial_call,{proc_lib,init_p,5}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[<0.183.0>,<0.274.0>,<0.337.0>,<0.375.0>,<0.387.0>,<0.371.0>,
         <0.310.0>,<0.326.0>,<0.226.0>,<0.262.0>,<0.210.0>,<0.218.0>,
         <0.153.0>,<0.165.0>,<0.177.0>,<0.171.0>,<0.159.0>,<0.135.0>,
         <0.147.0>,<0.141.0>,<0.123.0>,<0.129.0>,<0.77.0>]},
 {dictionary,[{'$ancestors',[riak_core_sup,<0.76.0>]},
              {'$initial_call',{supervisor_pre_r14b04,init,1}}]},
 {trap_exit,true},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.75.0>},
 {total_heap_size,1974},
 {heap_size,987},
 {stack_size,9},
 {reductions,8777},
 {garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,10},
                      {minor_gcs,2}]},
 {suspending,[]}]

节点3:

Node: 'mfmn3@127.0.0.1', Process: <0.80.0>
[{registered_name,riak_core_vnode_sup},
 {current_function,{gen_server,loop,6}},
 {initial_call,{proc_lib,init_p,5}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[<0.152.0>,<0.167.0>,<0.179.0>,<0.185.0>,<0.182.0>,<0.173.0>,
         <0.176.0>,<0.170.0>,<0.161.0>,<0.164.0>,<0.158.0>,<0.155.0>,
         <0.137.0>,<0.143.0>,<0.149.0>,<0.146.0>,<0.140.0>,<0.128.0>,
         <0.134.0>,<0.131.0>,<0.125.0>,<0.77.0>]},
 {dictionary,[{'$ancestors',[riak_core_sup,<0.76.0>]},
              {'$initial_call',{supervisor_pre_r14b04,init,1}}]},
 {trap_exit,true},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.75.0>},
 {total_heap_size,3194},
 {heap_size,2584},
 {stack_size,9},
 {reductions,4507},
 {garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,10},
                      {minor_gcs,10}]},
 {suspending,[]}]

3个节点的vnode worker 加起来刚好22 + 23 + 22 - 3 = 64

(mfmn3@127.0.0.1)3> supervisor:count_children(riak_core_vnode_sup).
[{specs,1},{active,21},{supervisors,0},{workers,21}]
(mfmn3@127.0.0.1)4>

减去3的原因。

从上面那张图可以看出, riak_core_vnode_master负责与vnode的通信,这些vnode都是fsm,如:

获取当前节点的所有vnode:

(mfmn3@127.0.0.1)8> riak_core_vnode_master:all_nodes(mfmn_vnode).
[<0.173.0>,<0.179.0>,<0.185.0>,<0.143.0>,<0.155.0>,
 <0.164.0>,<0.182.0>,<0.170.0>,<0.161.0>,<0.140.0>,<0.146.0>,
 <0.152.0>,<0.158.0>,<0.176.0>,<0.167.0>,<0.149.0>,<0.137.0>,
 <0.125.0>,<0.128.0>,<0.131.0>,<0.134.0>]
(mfmn3@127.0.0.1)9>

这也再次证明了该节点的vnode个数为21.

向某个vnode发出Ping请求

这个例子是try-try-try的例子:


前面会携带一个Pid,而这个Pid是根据hash在ets表中索引出来的,这个Pid是vnode 的Pid,根据这个Pid可以索引到具体的vnode,最后Mod:handle_command是用户的回调函数。

如果master没有找到对应的vnode,那么他会新建一个vnode:

get_vnode(Idx, State=#state{vnode_mod=Mod}) ->
    case idx2vnode(Idx, State) of
        no_match ->
            {ok, Pid} = riak_core_vnode_sup:start_vnode(Mod, Idx),
            MonRef = erlang:monitor(process, Pid),
            add_vnode_rec(#idxrec{idx=Idx,pid=Pid,monref=MonRef}, State),
            Pid;
        X -> X
    end.

因为vnode下面是存储后端,所以只要定位到vnode就可以访问后端存储。


下面是try try try对应的代码:

start(_StartType, _StartArgs) ->
    case mfmn_sup:start_link() of
        {ok, Pid} ->
            ok = riak_core:register([{vnode_module, mfmn_vnode}]),
            ok = riak_core_ring_events:add_guarded_handler(mfmn_ring_event_handler, []),
            ok = riak_core_node_watcher_events:add_guarded_handler(mfmn_node_event_handler, []),
            ok = riak_core_node_watcher:service_up(mfmn, self()),
            {ok, Pid};
        {error, Reason} ->
            {error, Reason}
    end.

stop(_State) ->
    ok.

启动master, 注册vnode, 铁添加mfmn_ring_event_handler,mfmn_node_event_handler...

下面就讲解一下try try try 的例子,高手勿喷!!!



第二个例子 Riak Core, The vnode

这是一个Real Time Stastics,简称RTS--实时统计应用。

这个系统要解决的两个问题是解析记录和分发记录,这交给entry vnode处理;第二个时接收实时统计,交给stat vnode处理。

注意

Entry = DocIdx = riak_core_util:chash_key({list_to_binary(Client), term_to_binary(now())}), 
Stat = riak_core_util:chash_key({list_to_binary(Client), list_to_binary(StatName)}),

从哈希上可以看出,rts只支持单客户端。

什么是vnode

-   vnode是一个虚拟节点,和物理节点不一样
-   一个虚拟节点对应一个`erlang process`
-   一个虚拟节点是一个behaviour - gen_fsm behaviour
-   一个虚拟节点处理进来的请求
-   一个虚拟节点可能会存储数据,这些数据可以被以后检索到
-   很多虚拟节点会运行在同一个物理节点上
-   每个虚拟机都有一个主虚拟节点,他主要用于和它的所有存活的节点保持联系

如你所见,虚拟节点要处理很多东西,不过Basho已经帮我们处理掉,我们只要实现所提供的`vnode behaviour`即可。用户只要理解输入和输出,然后定义所需的回调函数即可。

生命周期

init/1和termiante/2回调函数是虚拟节点的生命边缘,既是起止和终止位置,当一个连接到vnode的进程崩溃,那么handle_exit/3将会被调用。

init([Index]) -> Result

Index :: int() >= 0 
Result :: {ok, State} 
State :: term()

其中Index为VNode的hash值。

rts注册了3种vnode -- rts_vnode、rts_entry_vnode、 rts_stat_vnode、 对应的master vnode 分别为:rts_vnode_master、rts_entry_vnode_master、rts_stat_vnode_master。

每种vnode负责不同服务. rts_vnode提供ping服务, rts_entry_vnode提供日志分析服务, rts_stat_vnode对日志分析结果进行统计的服务。

terminate(Reason, State)

Reason      :: normal | shutdown | {shutdown, term()} | term()
State       :: term()
Result      :: term()

用于vnode清理资源,由于entry 和 stat所有东西都是在内存中的,所以不用做清理工作,直接交由erlang vm处理即可:

terminate(_Reason, _State) ->
    ok.

handle_exit(Pid, Reason, State) -> Result

Pid         :: pid()
Reason      :: term()
State       :: term()
Result      :: {noreply, NewState}
             | {stop, NewState}

当列链接到该vnode的进程挂掉时,这个回调函数将被调用,返回值有两种选择:1. 返回{stop, NewState}, 这样vnode也会被停止掉;2.返回{noreply, NewState},Vnode继续工作。

Commands

所有vnode的请求都变成命令请求。例如,一个riak kv的“get”请求最终会被handle_command处理,这个handle_command在vnode里定义。

为了实现一个命令,你需要增加一个新的handle_command/3函数,用于匹配到来的请求。例如:为了得到一个{get, StateName}的统计请求,需要增加一个handle_command({get, StatName}, ...)。

handle_command(Request, Sender, State) -> Result

Request     :: term()
Sender      :: sender()
State       :: term()
NewState    :: term()
Result      :: {reply, Reply, NewState}
             | {noreply, NewState}
             | {stop, Reason, NewState}

请求可以是任何东西,但经常是一个标签化的元组,Sender代表客户端进程,但经常是一个不透明的值,这个值用在riak_core_vnode:reply/2中。State更像一个gen_server state,主要用于跟踪回调函数轨迹。

有3中返回值:

1) reply: 发送Reply给客户端

2) noreply: 不发送应答

3) stop: 中断vnode

entry vnode 需要比较传进来的日志,然后在转发出去:

handle_command({entry, Client, Entry}, _Sender, #state{reg=Reg}=State) ->
    io:format("~p~n", [{entry, State#state.partition}]),
    lists:foreach(match(Client, Entry), Reg),
    {noreply, State}.

stat vnode就像一个迷你的Redis, 支持本地更新。

handle_command({get, StatName}, _Sender, #state{stats=Stats}=State) ->
    Reply =
        case dict:find(StatName, Stats) of
            error ->
                not_found;
            Found ->
                Found
        end,
    {reply, Reply, State};

handle_command({set, StatName, Val}, _Sender, #state{stats=Stats0}=State) ->
    Stats = dict:store(StatName, Val, Stats0),
    {reply, ok, State#state{stats=Stats}};

handle_command({incr, StatName}, _Sender, #state{stats=Stats0}=State) ->
    Stats = dict:update_counter(StatName, 1, Stats0),
    {reply, ok, State#state{stats=Stats}};

handle_command({incrby, StatName, Val}, _Sender, #state{stats=Stats0}=State) ->
    Stats = dict:update_counter(StatName, Val, Stats0),
    {reply, ok, State#state{stats=Stats}};

handle_command({append, StatName, Val}, _Sender, #state{stats=Stats0}=State) ->
    Stats = try dict:append(StatName, Val, Stats0)
            catch _:_ -> dict:store(StatName, [Val], Stats0)
            end,
    {reply, ok, State#state{stats=Stats}};

handle_command({sadd, StatName, Val}, _Sender, #state{stats=Stats0}=State) ->
    F = fun(S) ->
                sets:add_element(Val, S)
        end,
    Stats = dict:update(StatName, F, sets:from_list([Val]), Stats0),
    {reply, ok, State#state{stats=Stats}}.

"Covering" Commands

riak_core_vnode_master:coverage命令的回调为handle_coverage/4,这是一个很方便的操作,例如:可以用在列出riak的keys, 或者二级索引的范围查找。注意,首先,我们没有正在拉取对象。他所有的操作都落到vnode中去,这也意味着它是非常的高效的。比较酷的事情是这就好像是在本地操作一样,让你高性能的查询主键,并且根据匹配返回相应的对象;这是一个有效的方当使用像leveldb这种有序的存储后端时。

Handoff

handoff会在一个vnode意识到自己不是一个正确的node时会触发。如 :1. 由于增加/删除节点导致环的改变;2.一个node down掉后又up了

Riak Core实现了hinted handoff, hint 是一段数据,用于直线所在分区的vnode。实现handloff看起来比较困难,只要记住它的主要目的是vnode之间的数据传输就行了,如果你的vnode只是用来计算,那么可以无视它的存在。

handoff的成员有:is_empty/1, delete/1, handoff_starting/2, handoff_cancelled/1, encode_handoff_item/2, handle_handoff_data/2,handle_handoff_command/3, and handoff_finished/2.

is_empty(State) -> Result

State       :: term()
NewState    :: term()
Result      :: {true, NewState}
             | {false, NewState}

一旦容器确定了一个vnode位置发生变化时,它的第一个操作就是确定这里是否有任何的数据需要被传输,如果需要则返回true否则返回false。当一个vnode被认为是空的话,delete/3将被调用。

例子中的stat vnode检测stats dict的大小来确定其是否为空。

is_empty(State) ->
    case dict:size(State#state.stats) of
        0 -> {true, State};
        _ -> {false, State}
    end.

delete(State) -> Result

State       :: term()
NewState    :: term()
Result      :: {ok, NewState}

如果vnode没有数据需要传输了,容器就会调用delete。

handoff_starting(TargetNode, State) -> Result

TargetNode  :: node()
Result      :: {true, NewState} | {false, NewState}
State       :: term()
NewState    :: term()

当handoof一定发生的时候,容器就会调用handoff_starting/2,vnode最后会指示handoff是否会发生,返回true表示继续,返回false表示取消。vnode可能会有很多策略来决定它的负载,或者在超载的时候选择不参与数据传输.目标节点也是一个数据传输节点。

handoff_cancelled(State) -> Result

State       :: term()
NewState    :: term()
Result      :: {ok, NewState}

传输管理可以设置并发传输的操作数量,默认是4,但是可以调整。如果并发数量超标,那末容器就会调用handoff_cancelled/1,这时候你可以撤销在handoff_starting/2完成的事情。

如果在handoff期间发生错误,handoff_cancelled/1也会被调用。

encode_handoff_item(K, V) -> Result

K           :: {Bucket, Key}
Bucket      :: riak_object:bucket()
Key         :: riak_object:key()
V           :: term()
Result      :: binary()

这个函数用于容器加码数据,如序列化数据,需要了解的3件事是:

1) Key和Value是一起加码的,比如,他们需要一起访问

2) 这个函数必须返回二进制

3) 和handle_handle_off_data/2一起工作

如:

handle_handoff_data(Data, #state{stats=Stats0}=State) ->
    {StatName, Val} = binary_to_term(Data),
    Stats = dict:store(StatName, Val, Stats0),
    {reply, ok, State#state{stats=Stats}}.

    encode_handoff_item(StatName, Val) ->
    term_to_binary({StatName,Val}).                                   

handle_handoff_data(BinObj, State) -> Result

BinObj      :: binary()
State       :: term()
NewState    :: term()
Result      :: {reply, ok, NewState}
             | {reply, {error, Error}, NewState}

这个函数主要用来反序列化handoff data, 他的主要工作从而机制对象中重构vnode 的 state, 如果在解码数据时发生错误,那么返回{error, Error}来描述错误。

为了解码数据,例子中使用了binary_to_term/1并且把它插入到本地词典中。

handle_handoff_data(Data, #state{stats=Stats0}=State) ->
    {StatName, Val} = binary_to_term(Data),
    Stats = dict:store(StatName, Val, Stats0),
    {reply, ok, State#state{stats=Stats}}.

handle_handoff_command(Request, Sender, State) -> Result

Request     :: term()
Sender      :: sender()
State       :: term()
NewState    :: term()
Result      :: {reply, Reply, NewState}
             | {noreply, NewState}
             | {forward, NewState}
             | {drop, NewState}
             | {stop, Reason, NewState}

这个回调函数和handle_command/3非常相识,不同的是是在一个请求到达handoff时被调用。有两个额外的返回值:继续或者终止. 其中终止和noreply的行为是一样的,只是它用于提醒这是dropping操作,你也可以不实现它。

如果你想要你的节点传输数据,那么你必须实现?FOLD_REQ 在handle_handoff_command/3中。你必须这样做,因为handoff manager 通过这个方法来迭代你的数据。?FOLD_REQ是一个#riak_core_fold_req_v1的record,这个record包含了一个foldfun函数和一个acc0 (accumulator)迭代器。foldfun函数需要3个参数: the key, value,和accumulator.也就是说如果你的数据格式不支持foldfun,那么就需要手动调整。例如,如果你的数据是在是在一个列表里面,那么你应该实现一个适配函数来转化。

F = fun({Key,Val}, Acc) -> FoldFun(Key, Val, Acc) end,
Acc = lists:foldl(F, Acc0, State#state.data),

...
例子中的stat vnode使用一个dict,它支持3个参数的fold function, 迭代器是一个不透明的值,并且要和socket保持联系,定期的出发同步命令。有兴趣可以看一下handoff sender. 最后,确保返回迭代器的最终的值。

handle_handoff_command(?FOLD_REQ{foldfun=Fun, acc0=Acc0}, _Sender, State) ->
    Acc = dict:fold(Fun, Acc0, State#state.stats),
    {reply, Acc, State}.

我也不知道fold request在vnode behaviour的回调,在下一天在讨论。

handoff_finished(TargetNode, State) -> Result

TargetNode  :: node()
Result      :: any()
State       :: term()

当所有数据都传输到目标节点时,这个函数将会被调用,这个返回值可以是任何值,这个返回值会被容器忽略掉。

日志分析到日志统计

rts提供了http的接口方便用户录入数据,其中rts_wm_entry:process_post的数据结构如下

Client: "progski"
Entry: "0.0.0.0 - - [21/Mar/2011:18:18:19 +0000] \"GET /blog/2011/aol_meet_riak.html HTTP/1.1\" 200 5865 \"http://www.google.com/\" \"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16\""

Client是gunzip -c progski.access.log.gz | ./replay progski传递过来的, progski 为client,日志格式如下:

[_Host, _, _User, _Time, Req, Code, BodySize, _Referer, Agent]
0.0.0.0 - - [21/Mar/2011:18:47:27 +0000] "GET /blog/2011/aol_meet_riak.html HTTP/1.1" 200 12754 "-" "Java/1.6.0_24"

然后,entry master vnode根据哈希来调用entry vnode, entry vnode 切分日志,把日志切分为[_Host, _, _User, _Time, Req, Code, BodySize, _Referer, Agent],然后把每一项哈希出来,交由stat master vnode转发到对应的stat vnode中去。

PrefList = riak_core_apl:get_apl(DocIdx, 1, rts_entry),
    [IdxNode] = PrefList,
    rts_entry_vnode:entry(IdxNode, Client, Entry).

发送命令:

riak_core_vnode_master:command(IdxNode,
                                   {entry, Client, Entry},
                                   ?MASTER).

其中?MASTER为rts_entry_vnode_master.


如图:


最后交给stat vnode 进行统计。

游戏开发实战:如何用旋转矩阵实现2D角色平滑转向(附Unity代码) 本文深入探讨了在Unity游戏开发中,如何运用旋转矩阵原理实现2D角色的平滑转向。文章从核心理论出发,提供了计算目标旋转、实现平滑插值(Lerp与SmoothDamp)的完整C#代码,并解决了与动画系统、物理引擎协同的常见难题,帮助开发者提升游戏操作手感与视觉流畅度。 阅读详情

相关推荐

OpenManus本地部署实战:从源码编译到浏览器路径优化全解析

本文详细解析了OpenManus本地部署的全过程,从源码编译到浏览器路径优化。涵盖环境准备、源码获取、模型配置、依赖安装等关键步骤,特别针对Windows系统下的chrome.exe路径修改提供了实用解决方案,帮助开发者高效完成部署并优化性能。

weixin_28826545的博客 379

(1)riak_core基本原理

一、riak_core基本原理 1. 基于dynamo设计的riak_core 通过某种hash算法,每份数据会对应着一个唯一的整数。所有数据这样处理后就会映射到一个整数区间上。 对于riak_core,它管理着一个整数范围为[0-2^160]整数空间,这个空间形成一个首尾相连的环。 riak_core把这个环平均划分成多个分区partition(默认是64个分区)

sinat_22308473的博客 1227

新手也能玩转!用Panosim+MATLAB/Simulink搭建你的第一个智能驾驶仿真场景(保姆级图文)

本文为新手提供了使用Panosim和MATLAB/Simulink搭建智能驾驶仿真场景的详细教程。从环境准备、基础场景创建到仿真模型构建,一步步指导用户完成第一个智能驾驶仿真项目,帮助零基础用户快速上手并体验智能驾驶仿真的乐趣。

weixin_29090089的博客 182

对Riak Core的探索 (4) 数据的分布及处理步骤

haogongju、人人IT网、59n南龙、360doc不要抄我的烂博客了,私人备忘用。 [size=x-large]三、Riak Core系统的数据的分布和处理步骤[/size] 从原理上讲,Riak Core通过hash算法将数据随机均匀的分布在一个环上,数据的hash值也就是在环上的位置(源码中常用Index表示),知道了Index就知道了对应的分区partition,知道了...

好记性不如烂博客 260

基于CANoe的Basic Diagnostics ECU (UDS)

基于CANoe的Basic Diagnostics ECU (UDS)

farmer00的博客 9153

使用VNC可视化Docker容器

Docker容器可视化

Robert_Q的博客 1万+

Riak 简介,第 1 部分: 与语言无关的 HTTP API

转载:http://www.ibm.com/developerworks/cn/opensource/os-riak1/index.html 简介 典型的现代关系数据库在某些类型的应用程序中表现平平,难以满足如今的互联网应用程序的性能和可扩展性要求。因此,需要采用不同的方法。在过去几年中,一种新的数据存储类型变得非常流行,通常称为 NoSQL,因为它可以直接解决关系数据库的一些缺陷

zhangxinrun的专栏 5023

别再到处找教程了!Windows下用FFmpeg+Mediamtx+VLC搭建本地RTSP流媒体服务器,保姆级配置流程

本文详细介绍了在Windows系统下使用FFmpeg、Mediamtx和VLC搭建本地RTSP流媒体服务器的完整流程。从环境准备到核心配置,再到推流和拉流的实战技巧,提供了保姆级的避坑指南和优化建议,帮助开发者快速实现稳定的流媒体服务部署。

weixin_42614269的博客 212

对Riak Core的探索 (1) Hello

haogongju、人人IT网、59n南龙、360doc不要抄我的烂博客了,私人备忘用。 [size=x-large]基于Riak Core的开发指南[/size] [size=large]1. hello, Riak Core[/size] 从riak-core-first-multinode开始一个hello world应用(简称mfmn):访问[url=https:/...

好记性不如烂博客 310

Halcon 3D点云处理实战:从PLY文件读取到曲面匹配的完整流程(附避坑指南)

本文详细介绍了Halcon在3D点云处理中的完整流程,从PLY文件读取到曲面匹配,特别强调了3D算子的应用技巧和避坑指南。通过实战案例和参数优化建议,帮助开发者高效处理工业视觉检测中的复杂点云数据,提升匹配精度和性能。

weixin_42535720的博客 278

2026.7.9:2026.7.9最新的Ubuntu26.04安装docker-ce

本文介绍了在Ubuntu 26.04系统上安装Docker CE的完整步骤。首先需要卸载旧版本的Docker组件,然后通过设置官方仓库进行安装。具体步骤包括:更新系统、安装必要依赖、添加Docker GPG密钥、配置稳定版仓库源、安装Docker Engine及containerd。文章还提供了安装特定版本Docker的方法,并说明了如何将用户加入docker组以获取权限,最后设置Docker开机自启。整个过程详细清晰,适合在Ubuntu系统上部署Docker环境的用户参考。

拥抱具身智能,昇腾Ascend C 516

对Riak Core的探索 (2) 基本原理

haogongju、人人IT网、59n南龙、360doc不要抄我的烂博客了,私人备忘用。 Riak Core采用一致性哈希算法分布数据。 [quote="《分布式系统原理介绍》第2节 分布式系统原理 by刘杰"]“所谓分布式系统顾名思义就是利用多台计算机协同解决单台计算机所不能解决的计算、存储等问题。单机系统与分布式系统的最大的区别在于问题的规模,即计算、存储的数据量的区别。将一个单机...

好记性不如烂博客 266

基于simulink的BMS系统中电池单体故障隔离与恢复建模

本文介绍了使用Simulink构建BMS电池单体故障诊断与容错控制模型的方法。主要内容包括:1)搭建12串锂电池组模型;2)实现单体故障注入(过压、断线等);3)设计故障诊断与隔离模块(采用Stateflow状态机);4)开发恢复判断逻辑(需满足电压、温度等条件);5)系统监控与仿真设置。文章还提供了工程实践建议,如防环流设计、通信冗余等,并指出进阶方向(多故障处理、AI预警等)。该模型适用于新能源汽车、储能系统的BMS设计,可提高系统可靠性和安全性。

xiaoheshang_123的博客 140

Riak Core Guide 3

Learn Riak Core Step By Step 3 Riak Core, Conflict Resolution 这一章主要描述最终一致性和如何实现强一致性。 Object 非重重要的一个数据结构: rts_obj : #rts_obj | not_found record( rts_obj, { val :: #incr |

Riak, Spark, Golang, Erlang, 云存储, 云计算, 数据挖掘 4152

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Riak Core Guide 2

Learn Riak Core Step By Step 2 Riak Core, The Coordinator What is a Coordinator? 顾名思义, Coordinator即使一个协调者,主要工作就是用来协调进来的请求。它强行执行N, R, and W的一致性语义,并且执行想read repair的anti-entropy 服务。足药用在分布式集群中,当出现冲

Riak, Spark, Golang, Erlang, 云存储, 云计算, 数据挖掘 3201

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Riak KV性能优化:提升分布式存储吞吐量的10个关键策略

Riak KV作为一款高性能的分布式Key/Value存储系统,在大规模数据场景下的吞吐量表现直接影响业务响应速度。本文将分享10个经过实践验证的性能优化策略,帮助你充分释放Riak KV的存储潜力,显著提升系统吞吐量与稳定性。 ## 1. 合理配置后端存储引擎 选择适合业务场景的存储引擎是性能优化的基础。Riak KV提供了多种后端实现: - **LevelDB后端**:[src/riak_

gitblog_00711的博客 1147

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

CANN/GE分组卷积拆分Pass示例

This sample demonstrates a custom pass for splitting grouped convolution, providing two verification methods: online inference and ATC offline model compilation. The sample uses eager style API and fu

gitblog_01073的博客 725

并行分布式框架:Celery、rq、funboost

Celery是一个异步任务的调度工具,也可以叫做 "分布式任务队列(Distributed Task Queue)"。

freeking101的博客 5万+

(3)riak_core系统的工作方式

三、riak_core系统的工作方式 从原理上讲,riak_core通过一致性hash算法将数据随机均匀的分布在一个环上,对这些数据的操作可以并发的进行,因此riak_core本质上还是一个数据并行的分布式系统。 因此,基于riak_core构建分布式系统涉及到两个问题: 对数据如何分布:riak_core通过某种hash算法将数据随机均匀的分布在一个环上。选取那种hash算

sinat_22308473的博客 492

WKID 对应的 坐标系

4001 GCS_Airy_1830 4002 GCS_Airy_Modified 4003 GCS_Australian 4004 GCS_Bessel_1841 4005 GCS_Besse

深海之蓝的个人专栏 6457

对Riak Core的探索 (7)

haogongju、人人IT网、59n南龙、360doc不要抄我的烂博客了,私人备忘用。 关于Riak Core的使用,有许多例子可以探索。最经典最复杂的莫过于riak 这个NoSQL数据库本身,不过riak本身不是一个实现,几乎没有erlang代码,它更像是胶水,将具体的KV实现(riak_kv)与riak_core(当然还有其它应用,比如日志、统计等等其它应用)粘结起来。 riak...

好记性不如烂博客 247

Riak VClock

Riak VClock 关于向量时钟的概念,在这里就多讲了,大家可以参照一下Dynamo的论文了解一下,向量时钟在分布式主要用于解决一致性性问题,可以和CRDTs一起看。 下面的源代码是参照riak中的,就是把它翻译为elixir格式而已,基本不变。 时钟主要出现的情况有网络分区和并行更新。 这样只会丢掉一些向量时钟的信息,即数据更新过程的信息,但是不会丢掉实实在在的数据。

Riak, Spark, Golang, Erlang, 云存储, 云计算, 数据挖掘 3009

EStateBox For CRDTs

EStateBox For CRDTs

Riak, Spark, Golang, Erlang, 云存储, 云计算, 数据挖掘 2952

Redis Cluster Configure

bdrq: 在集群中,如果master挂掉,那么slave将被提升为master, master再次启动是,会变成slave nutcracker 1.编译nutcracker $ CFLAGS="-ggdb3 -O0" ./configure --enable-debug=full$ make$ sudo make install 2.Config nutcracker alph

Riak, Spark, Golang, Erlang, 云存储, 云计算, 数据挖掘 2740
上一篇: Clojure
下一篇: 关于uboot.map 文件的作用
laohan_
博客等级 码龄15年 112粉丝 224原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值