阅读更多
项目中需要用到riak数据库,大致学习了一下,安装并进行集群。
环境:ubuntu10.10 64bit ,jdk1.6.0_24,erlang5.8,riak-search_0.14.0-1_amd64.deb
1安装并修改配置文件
修改当前节点的配置文件
sudo gedit /etc/riaksearch/app.config
将{riak_web_ip, "127.0.0.1"}改为{riak_web_ip, "192.168.1.10"}//192.168.1.10是我本地ip
注:此配置文件中有几个地方需要配置ip,riak支持http接口、https接口,客户端请求时需要什么接口配置哪个接口即可,我这里用的是http
%% HTTPS interface will bind.
{https, [{ "127.0.0.1", 8098 }]},//这里是https
下面还有一个ip 地址,此地址为配置不同的存储后端,设为本地ip
%% pb_ip is the IP address that the Riak Protocol Buffers interface
%% will bind to. If this is undefined, the interface will not run.
{pb_ip, "192.168.1.100" },
修改节点参数配置文件
sudo gedit /etc/riaksearch/vm.args,修改-name 参数的值,即将 -name
[email protected] 改为-name
[email protected]
2启动riaksearch
riaksearch console启动riak并运行控制台,可查看到启动信息
riaksearch start后台启动无任何信息
riaksearch ping查看是否启动成功pong成功pang失败
3加入集群
riaksearch-admin join
[email protected]
查看集群内结点:erl内输入 nodes().
4建立一个bucket
启动一个客户端{ok,Client}=riak:local_client().
建立一个bucket
Client:set_bucket(<<"regions">>,[{precommit, [{struct,[{<<"mod">>,<<"riak_search_kv_hook">>}, {<<"fun">>,<<"precommit">>}]}]}]).
在建立bucket的时候set了一些属性,大致看了一下官方文档,有很多还不明白的地方
Available properties:
* n_val (integer > 0) – the number of replicas for objects in this bucket
* allow_mult (true or false) – whether to allow sibling objects to be created (concurrent updates)
* last_write_wins (true or false) – whether to ignore object history (vector clock) when writing
* precommit – precommit hooks
* postcommit – postcommit hooks
* r, w, dw, rw – default quorum values for operations on keys in the bucket. Valid values are:
o "all" – all nodes must respond
o "quorum" – (n_val/2) + 1 nodes must respond. This is the default.
o "one" – equivalent to 1
o Any integer – must be less than or equal to n_val
* backend – when using riak_kv_multi_backend, which named backend to use for the bucket
Overview #
Pre- and Post- Commit hooks are invoked before or after a riak_object is persisted and can greatly enhance the functionality of any application. Commit hooks can:
1. allow a write to occur with an unmodified object
2. modify the object
3. Fail the update and prevent any modifications
Post-commit hooks are notified after the fact and should not modify the riak_object. Updating riak_objects in post-commit hooks can cause nasty feedback loops which will wedge the hook into an infinite cycle unless the hook functions are carefully written to detect and short-circuit such cycles.
Pre- and post-commit hooks are defined on a per-bucket basis and are stored in the target bucket’s properties. They are run once per successful response to the client.
Configuration #
Configuring either pre- or post-commit hooks is very easy. Simply add a reference to your hook function to the list of functions stored in the correct bucket property. Pre-commit hooks are stored under the bucket property precommit. Post-commit hooks use the bucket property postcommit.
Pre-commit hooks can be implemented as named Javascript functions or as Erlang functions. The configuration for each is given below:
Javascript: {"name": "Foo.beforeWrite"}
Erlang: {"mod": "foo", "fun": "beforeWrite"}
Post-commit hooks can be implemented in Erlang only. The reason for this restriction is Javascript cannot call Erlang code and, thus, is prevented from doing anything useful. This restriction will be revisited when the state of Erlang/Javascript integration is improved. Post-commit hooks use the same function reference syntax as pre-commit hooks.
See the map/reduce documentation for steps to define your own pre-defined Javascript named functions.
Pre-Commit Hooks #
API & Behavior #
Pre-commit hook functions should take a single argument, the riak_object being modified. Remember that deletes are also considered “writes” so pre-commit hooks will be fired when a delete occurs. Hook functions will need to inspect the object for the X-Riak-Deleted metadata entry to determine when a delete is occurring.
Erlang pre-commit functions are allowed three possible return values:
1. A riak_object — This can either be the same object passed to the function or an updated version. This allows hooks to modify the object before they are written.
2. fail — The atom fail will cause Riak to fail the write and send a 403 Forbidden along with a generic error message about why the write was blocked.
3. {fail, Reason} — The tuple {fail, Reason} will cause the same behavior as in #2 with the addition of Reason used as the error text.
Errors that occur when processing Erlang pre-commit hooks will be reported in the sasl-error.log file with lines that start with “problem invoking hook”.
Erlang Pre-commit Example:
%% Limits object values to 5MB or smaller
precommit_limit_size(Object) ->
case erlang:byte_size(riak_object:get_value(Object)) of
Size when Size > 5242880 -> {fail, "Object is larger than 5MB."};
_ -> Object
end.
Javascript pre-commit functions should also take a single argument, the JSON encoded version of the riak_object being modified. The JSON format is exactly the same as Riak’s map/reduce. Javascript pre-commit functions are allowed three possible return values:
1. A JSON encoded Riak object — Aside from using JSON, this is exactly the
same as #1 for Erlang functions. Riak will automatically convert it back to it’s native format before writing.
2. fail — The Javascript string “fail” will cause Riak to fail the write in exactly the same way as #2 for Erlang functions.
3. {"fail": Reason} — The JSON hash will have the same effect as #3 for Erlang functions. Reason must be a Javascript string.
Javascript Pre-commit Example
// Makes sure the object has JSON contents
function precommitMustBeJSON(object){
try {
Riak.mapValuesJson(object);
return object;
} catch(e) {
return {"fail":"Object is not JSON"};
}
}
Chaining #
The default value of the bucket precommit property is an empty list. Adding one or more pre-commit hook functions, as documented above, to the list will cause Riak to start evaluating those hook functions when bucket entries are created, updated, or deleted. Riak stops evaluating pre-commit hooks when a hook function fails the commit.
Pre-commit Validation Example #
Pre-commit hooks can be used in many ways in Riak. One such way to use pre-commmit hooks is to validate data before it is written to Riak. Below is an example that uses Javascript to validate a JSON object before it is written to Riak.
//Sample Object
{
"user_info": {
"name": "Mark Phillips",
"age": "25",
},
"session_info": {
"id": 3254425,
"items": [29, 37, 34]
}
}
var PreCommit = {
validate: function(obj){
// A delete is a type of put in Riak so check and see what this
// operation is doing
if (obj.values[[0]][['metadata']][['X-Riak-Deleted']]){
return obj;
}
// Make sure the data is valid JSON
try{
data = JSON.parse(obj.values[[0]].data);
validateData(data);
}catch(error){
return {"fail": "Invalid Object: "+error}
}
return obj;
}
};
function validateData(data){
// Validates that user_info object is in the data
// and that name and age aren't empty, finally
// the session_info items array is checked and validated as
// being populated
if(
data.user_info != null &&
data.user_info.name != null &&
data.user_info.age != null &&
data.session_info.items.length > 0
){
return true;
}else{
throw( "Invalid data" );
}
}
Post-Commit Hooks #
API & Behavior #
Post-commit hooks are run after the write has completed successfully. Specifically, the hook function is called by riak_kv_put_fsm immediately before the calling process is notified of the successful write. Hook functions must accept a single argument, the riak_object instance just written. The return value of the function is ignored. As with pre-commit hooks, deletes are considered writes so post-commit hook functions will need to inspect object metadata for the presence of X-Riak-Deleted to determine when a delete has occurred. Errors that occur when processing post-commit hooks will be reported in the sasl-error.log file with lines that start with “problem invoking hook”.
Post-commit Example (Erlang):
%% Creates a naive secondary index on the email field of a JSON object
postcommit_index_on_email(Object) ->
%% Determine the target bucket name
Bucket = erlang:iolist_to_binary([riak_object:bucket(Object),"_by_email"]),
%% Decode the JSON body of the object
{struct, Properties} = mochijson2:decode(riak_object:get_value(Object)),
%% Extract the email field
{<<"email">>,Key} = lists:keyfind(<<"email">>,1,Properties),
%% Create a new object for the target bucket
%% NOTE: This doesn't handle the case where the
%% index object already exists!
IndexObj = riak_object:new(Bucket, Key,<<>>, %% no object contents
dict:from_list(
[
{<<"content-type">>, "text/plain"},
{<<"Links">>,
[
{{riak_object:bucket(Object), riak_object:key(Object)},<<"indexed">>}]}
])),
%% Get a riak client
{ok, C} = riak:local_client(),
%% Store the object
C:put(IndexObj).
Chaining #
The default value of the bucket postcommit property is an empty list. Adding one or more post-commit hook functions, as documented above, to the list will cause Riak to start evaluating those hook functions immediately after data has been created, updated, or deleted. Each post-commit hook function runs in a separate process so it’s possible for several hook functions, triggered by the same update, to execute in parallel. All post-commit hook functions are executed for each create, update, or delete.
查询此bucket
Client:get_bucket(<<"regions">>).