slab_alloc_arena = 1 pid_file = "box.pid" logger="cat - >> Tarantool.log" primary_port = 33013 secondary_port = 33014 admin_port = 33015 rows_per_wal = 5000000 # space[0].enabled = 1 space[0].index[0].type = "HASH" space[0].index[0].unique = 1 space[0].index[0].key_field[0].fieldno = 0 space[0].index[0].key_field[0].type = "NUM" space[0].index[0].key_field[1].fieldno = 1 space[0].index[0].key_field[1].type = "NUM" space[0].index[1].type = "TREE" space[0].index[1].unique = 0 space[0].index[1].key_field[0].fieldno = 0 space[0].index[1].key_field[0].type = "NUM" space[0].index[2].type = "TREE" space[0].index[2].unique = 0 space[0].index[2].key_field[0].fieldno = 0 space[0].index[2].key_field[0].type = "NUM" space[0].index[2].key_field[1].fieldno = 2 space[0].index[2].key_field[1].type = "NUM" space[1].enabled = 1 space[1].index[0].type = "HASH" space[1].index[0].unique = 1 space[1].index[0].key_field[0].fieldno = 0 space[1].index[0].key_field[0].type = "NUM"
$ tarantool_box --init-storage tarantool/src/box/tarantool_box: space 0 successfully configured tarantool/src/box/tarantool_box: space 1 successfully configured tarantool/src/box/tarantool_box: creating `./00000000000000000001.snap.inprogress' tarantool/src/box/tarantool_box: saving snapshot `./00000000000000000001.snap' tarantool/src/box/tarantool_box: done
function increase_score(user_id, friend_id, action_type) -- local id = tonumber(user_id) local fid = tonumber(friend_id) if not id or not fid or not map_type_score[action_type] then return false end -- local dt = os.date('*t') local cd = box.time{year = dt.year; month=dt.month; day=dt.day} -- , local last_update = box.select('1', '0', id) if not last_update then last_update = box.insert('1',id,cd) end -- local difft = math.floor(( cd-box.unpack('i',last_update[1]) )/24/60/60) -- , if difft ~= 0 then if difft > 1 then -- , , -- , , table.insert(updates_in_fibers,id,box.fiber.wrap(function() _move_last_update(id, cd, difft) end)) difft = difft-1 else difft = 0 end box.update('1',id,'=p',1,cd) end -- local tup = box.select('0','0', id, fid) -- _get_score_koef if not tup then -- , local s_k = _get_score_koef(nil, nil, map_type_score[action_type], nil, cd) tup = box.insert('0', id, fid, s_k[1], cd, s_k[2]) else -- local s_k = _get_score_koef(box.unpack('i', tup[3])+difft, box.unpack('i', tup[2]), map_type_score[action_type], box.unpack('i',tup[4]), cd) -- , , tup = box.update('0',{id;fid},'=p=p=p',2, s_k[1],3,cd,4,s_k[2]) end return tup end
function _move_last_update(id, cd, diff) weights = box.space[0] for tup in weights.index[1]:iterator(box.index.EQ, id) do -- if box.unpack('i',tup[3]) < cd then weights:update({box.unpack('i',tup[1]); box.unpack('i',tup[2])},'=p', 3, box.unpack('i',tup[3])+diff) end end -- id table.remove(updates_in_fibers, id) end
function _get_score_koef(last_update, last_score, add_score, koef, current_date) local score = 0; if not last_score then -- , , score = add_score else if current_date == last_update then -- , score = last_score + add_score else -- , local diff = (current_date-last_update)/24/60/60*koef if diff > last_score then -- , , , - diff = last_score end -- , score = last_score + add_score - diff end end if add_score then -- , , , koef = score/box_pu_default['score_day'] end return {score,koef}; end
function get_top(user_id, count_users, ids) -- , ( "box_config_popular_user.lua") local id = tonumber(user_id) if not id then return false end local cu if not count_users then cu = box_pu_default['count_users'] else cu = tonumber(count_users) end local id_users = {} local count = 0 -- id , , - - , if ids then for id in string.gmatch(ids, "%d+") do id_users[tonumber(id)] = 1 count=count+1 end if(count < cu) then cu = count end end -- local ret local last_update = box.select('1', '0', id) -- 2 for iter = 1, 2 do local need_update = {} ret = {} for v in box.space[0].index[2]:iterator(box.index.LE, id) do -- - if not v or #ret == cu or box.unpack('i',v[0]) ~= id then break end -- , , if not ids or id_users[box.unpack('i',v[1])] == 1 then -- -- , if not updates_in_fibers[id] and box.unpack('i', v[3]) ~= box.unpack('i', last_update[1]) then table.insert(need_update, v) else -- table.insert(ret, v) end end end local need_another_req = 0 for i = 1, #need_update do local v = need_update[i] local s_k = _get_score_koef(box.unpack('i', v[3]), box.unpack('i', v[2]), 0, box.unpack('i',v[4]), box.unpack('i', last_update[1])) -- , if s_k[1] == 0 then box.delete('0',{v[0],v[1]}) else -- , , .. box.update('0',{v[0];v[1]},'=p=p=p',2, s_k[1],3,box.unpack('i', last_update[1]),4,s_k[2]) need_another_req = 1 end end if need_another_req == 0 then break end end return unpack(ret) end
map_type_score={user_page=100} -- increase_score, , , increase_score box_pu_default={count_users=10;score_day=30} -- - get_top - , .
dofile("box_config_popular_user.lua")
use strict; use DR::Tarantool ':constant', 'tarantool'; my $client = tarantool host => 'localhost', port => 33013, spaces => { 0 => { name => 'user_score', default_type => 'NUM', fields => [ qw(id fid score last_update koef), ], indexes => { 0 => { name => 'idx_id_fid', fields => [ 'id', 'fid' ] }, 1 => { name => 'idx_id', fields => [ 'id' ] }, 2 => { name => 'idx_id_score', fields => [ 'id', 'score' ] }, } }, 1 => { name => 'user_last_update', default_type => 'NUM', fields => [ qw(id last_update), ], indexes => { 0 => { name => 'idx_id', fields => [ 'id' ] }, } }, }; while(<>){ my $line = $_; my @params = split( " ", $line); $client->call_lua($params[0], @params[1..$#params],($params[0] eq 'increase_score' ? ('user_page') : ()); };
use Client::Tarantool; my $client = Client::Tarantool->new...
#!/usr/bin/perl use strict; use DR::Tarantool::AsyncClient 'tarantool'; use AnyEvent; use AnyEvent::Handle; my $cv = condvar AnyEvent; my $counts = {}; my $hdl; my $w; my $client; # my $done_sub = sub { $counts->{ae}--; $cv->send unless $counts->{ae}; }; # my $read_line_sub = sub { my $line = shift; my @params = split( " ", $line); $counts->{ae}++; $counts->{$params[0]}++; $client->call_lua($params[0], [@params[1..$#params],($params[0] eq 'increase_score' ? ('user_page') : ())], $done_sub); }; my $limit_concur_req = 12000; # - DR::Tarantool::AsyncClient->connect( host => '127.0.0.1', port => 33013, spaces => { 0 => { name => 'user_score', default_type => 'NUM', fields => [ qw(id fid score last_update koef), ], indexes => { 0 => { name => 'idx_id_fid', fields => [ 'id', 'fid' ] }, 1 => { name => 'idx_id', fields => [ 'id' ] }, 2 => { name => 'idx_id_score', fields => [ 'id', 'score' ] }, } }, 1 => { name => 'user_last_update', default_type => 'NUM', fields => [ qw(id last_update), ], indexes => { 0 => { name => 'idx_id', fields => [ 'id' ] }, } }, }, sub { ($client) = @_; $counts->{ae}++; $hdl = new AnyEvent::Handle fh => \*STDIN, on_error => sub { # my ($hdl, $fatal, $msg) = @_; AE::log error => $msg; $hdl->destroy; $cv->send; }, on_eof => $done_sub; my @start_request; # @start_request = (line => sub { my ($hdl, $line) = @_; $line =~ s/[\r\n]//g; $read_line_sub->($line) if $line; # - $hdl->push_read (@start_request) if $counts->{ae} < $limit_concur_req; }); $w = AnyEvent->timer (after => 0, interval => 1, cb => sub{ # $limit_concur_req += 1000 if $counts->{ae} < 1000; $hdl->push_read (@start_request) if $counts->{ae} < $limit_concur_req; }); } ); $cv->recv;
Source: https://habr.com/ru/post/194324/
All Articles