2016-02-07 26 views
5

Sto tentando di memorizzare alcuni dati nel bullone tempesta, ma non sono sicuro se questo sia il modo giusto per farlo o meno. Nell'id del dipendente della classe inferiore e il nome del dipendente viene memorizzato nella cache di una mappa hash. Per questo è stata effettuata una chiamata al database nella tabella Dipendente per selezionare tutti i dipendenti e compilare una mappa hash nel metodo di preparazione (è questo il posto giusto per inizializzare la mappa?).Memorizzazione nella cache di bulloni di tempesta

Dopo alcune registrazioni risulta (mentre è in esecuzione la topologia della tempesta), la topologia sta effettuando più connessioni di database e inizializzando la mappa più volte. Ovviamente voglio evitare questo, ecco perché voglio memorizzare nella cache il risultato in modo che non passi al database ogni volta. Per favore aiuto?

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; 
    }  
} 

SOLUZIONE ho creato mappa sincronizzato e il suo bel lavoro per me

private static Map<String, String> employeeIdToNameMap = Collections 
      .synchronizedMap(new HashMap<String, String>()); 
+0

Il codice sembra buono. Il tuo approccio per inizializzare HashMap in prepare() è assolutamente corretto. Informazioni su più connessioni al database: presumo che tu abbia più istanze del tuo bullone nella tua topologia (es. Parallelim_hint> 1). Pertanto, ogni istanza aprirà la propria connessione e questo è ragionevole. –

+0

Ho più altri bulloni accanto a questo bullone che ha parallelismo> 1, ma per questo bullone il parallelismo è 1 – big

risposta

1

Dal momento che si dispone di più attività bullone, è possibile contrassegnare employeeIdToNameMap statica e volatile. Inizializzare la mappa in questo modo -

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