在风暴螺栓中缓存

时间:2016-02-07 00:24:04

标签: java caching apache-storm

我试图在暴风雨中缓存一些数据,但不确定这是否是正确的方法。在下面的类中,员工ID和员工姓名被缓存到哈希映射中。为此,已对Employee表进行数据库调用以选择所有员工并在prepare方法中填充哈希映射(这是初始化映射的正确位置吗?)。

经过一些日志记录后(运行风暴拓扑),拓扑结构正在进行多个数据库连接并多次初始化映射。当然,我想避免这种情况,这就是为什么我要缓存结果,以便它不会每次都进入数据库。请帮帮忙?

# https://s3.amazonaws.com/iedu-attachments-question/5a989d787772b7fd88c063aff8393d34_1bee2d300c35eec13edf0a3af515a5a5.pdf
NUM_PROBS = 5

# Board looks like
#    1  2  3  4  5
#    6  7  8  9 10
#   11 12 13 14 15
#   16 17 18 19 20
#   21 22 23 24 25
WIDTH = 5
HEIGHT = 5

# display characters for printing:
WHITE = 'O'
BLACK = '#'
EMPTY = '.'

from itertools import product

def parse(s):
    """
    Input:  string of comma-delimited integers
              ex: "3, 12, 17, 22, 3, 9, 14, 10"
            format is num_white, *[white locations], num_black, *[black locations]

    Output: [white locations], [black locations]
              ex: [12, 17, 22], [9, 14, 10]
    """
    ints = [int(i) for i in s.split(',')]
    num_white = ints[0]
    num_black = ints[num_white + 1]
    return ints[1:num_white + 1], ints[-num_black:]

def location_to_coords(location):
    """
    Given a location on the board,
    return 0-based (y,x) coordinates

    ex: location_to_coords(16) returns (3, 0)
    """
    return divmod(location - 1, WIDTH)

def coords_to_location(y, x):
    """
    Given (y, x) coordinates,
    return a location on the board

    ex: coords_to_location(3, 0) returns 16
    """
    return y * WIDTH + x + 1

def print_board(whites, blacks):
    # make an empty board
    board = [[EMPTY] * WIDTH for row in range(HEIGHT)]
    # add white pieces
    for location in whites:
        y, x = location_to_coords(location)
        board[y][x] = WHITE
    # add black pieces
    for location in blacks:
        y, x = location_to_coords(location)
        board[y][x] = BLACK
    # show the result
    print('\n'.join(''.join(row) for row in board))

def make_dir_fn(dy, dx):
    """
    Given a direction, make a function
      which, given a location, returns
      the next location in that direction
      (or None if no such location exists)
    """
    def dir_fn(location):
        y, x = location_to_coords(location)
        if 0 <= y + dy < HEIGHT and 0 <= x + dx < WIDTH:
            return coords_to_location(y + dy, x + dx)
        else:
            return None
    return dir_fn

def make_lst_fn(dir_fn):
    """
    Given a direction function, make a function
      which, given a location, returns a list
      of all consecutive locations in that direction
      to the edge of the board
    """
    def lst_fn(location):
        result = []
        while True:
            location = dir_fn(location)
            if location is None:
                break
            else:
                result.append(location)
        return result
    return lst_fn

# direction functions (one step in the named direction)
left  = make_dir_fn( 0, -1)
right = make_dir_fn( 0,  1)
up    = make_dir_fn(-1,  0)
down  = make_dir_fn( 1,  0)

# relationships between direction functions
dir_fns = [left, right, up, down]
lst_fn  = {dir_fn: make_lst_fn(dir_fn) for dir_fn in dir_fns}
opposite_dir_fn = {left: right, right: left, up: down, down: up}

def attack_toward(location, dir_fn, whites, blacks):
    """
    Return a list of pieces captured by attacking toward given direction
    """
    # make sure attacker is white (swap if needed)
    if location in blacks:
        whites, blacks = blacks, whites
    # make sure we have a valid attacker
    if location not in whites:
        return []
    # make sure we have a space to move to
    next_location = dir_fn(location)
    if (next_location is None) or (next_location in whites) or (next_location in blacks):
        return []
    # get list of attacked locations
    attacked = lst_fn[dir_fn](next_location)
    captured = []
    for location in attacked:
        if location in blacks:
            captured.append(location)
        else:
            break
    return captured

def attack_away(location, dir_fn, whites, blacks):
    """
    Return a list of pieces captured by attacking away from given direction
    """
    # make sure attacker is white (swap if needed)
    if location in blacks:
        whites, blacks = blacks, whites
    # make sure we have a valid attacker
    if location not in whites:
        return []
    # make sure we have a space to move to
    next_location = opposite_dir_fn[dir_fn](location)
    if (next_location is None) or (next_location in whites) or (next_location in blacks):
        return []
    # get list of attacked locations
    attacked = lst_fn[dir_fn](location)
    captured = []
    for location in attacked:
        if location in blacks:
            captured.append(location)
        else:
            break
    return captured

attack_fns = [attack_toward, attack_away]

def main():
    for prob in range(NUM_PROBS):
        # get problem
        whites, blacks = parse(input())
        # pick an attacker, a direction, and an attack method
        for location, dir_fn, attack_fn in product(whites, dir_fns, attack_fns):
            captured = attack_fn(location, dir_fn, whites, blacks)
            # stop when a successful attack is found!
            if captured: break
        # display results
        if captured:
            print(", ".join(str(i) for i in sorted(captured)))
        else:
            print("NONE")

if __name__ == "__main__":
    main()

我创建了同步地图,它的工作正常我

public class TestBolt extends BaseRichBolt {
    private static final long serialVersionUID = 2946379346389650348L;
    private OutputCollector collector;
    private Map<String, String> employeeIdToNameMap;
    private static final Logger LOG = Logger.getLogger(TestBolt.class);

    @Override
    public void execute(Tuple tuple) {    
        String employeeId = tuple.getStringByField("employeeId");
        String employeeName = employeeIdToNameMap.get(employeeId);

        collector.emit(tuple, new Values(employeeId, employeeName));
        collector.ack(tuple);
    }

    @Override
    public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
        // TODO Auto-generated method stub
        this.collector = collector;
        try {
            employeeIdToNameMap = createEmployeIdToNameMap();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields(/*some fields*/));

    }

    private Map<String, String> createEmployeIdToNameMap() throws SQLException {
        final Map<String, String> employeeIdToNameMap = new HashMap<>();
        final DatabaseManager dbm = new PostgresManager();
        final String query = "select id, name from employee;";
        final Connection conn = dbm.createDefaultConnection();
        final ResultSet result = dbm.executeSelectQuery(conn, query);
        while(result.next()) {
            String employeId = result.getString("id");
            String name = result.getString("name");
            employeeIdToNameMap.put(employeId, name);
        }
        conn.close();
        return employeeIdToNameMap;
    }       
}

1 个答案:

答案 0 :(得分:1)

由于您有多个bolt任务,因此可以将employeeIdToNameMap标记为static和volatile。在准备中初始化地图 -

try {
 synchronized(TestBolt.class) {
    if (null == employeeIdToNameMap) {
    employeeIdToNameMap = createEmployeIdToNameMap();
    }
  }  
} catch (SQLException e) {
 ...
}