def zmq_sub(bind, tables, forwarder=False, green=False):
    """0mq fanout sub.

    This sub will use zeromq to fanout the events.

    :param bind: the zmq pub socket or zmq device socket.
    :param tables: the events of tables to follow.
    :param forwarder: set to True if zmq pub to a forwarder device.
    :param green: weather to use a greenlet compat zmq
    """
    logger = logging.getLogger("meepo.sub.zmq_sub")

    if not isinstance(tables, (list, set)):
        raise ValueError("tables should be list or set")

    if not green:
        import zmq
    else:
        import zmq.green as zmq

    ctx = zmq.Context()
    socket = ctx.socket(zmq.PUB)

    if forwarder:
        socket.connect(bind)
    else:
        socket.bind(bind)

    events = ("%s_%s" % (tb, action) for tb, action in
              itertools.product(*[tables, ["write", "update", "delete"]]))
    for event in events:
        def _sub(pk, event=event):
            msg = "%s %s" % (event, pk)
            socket.send_string(msg)
            logger.debug("pub msg: %s" % msg)
        signal(event).connect(_sub, weak=False)

    return socket
0mq fanout sub.

    This sub will use zeromq to fanout the events.

    :param bind: the zmq pub socket or zmq device socket.
    :param tables: the events of tables to follow.
    :param forwarder: set to True if zmq pub to a forwarder device.
    :param green: weather to use a greenlet compat zmq