You can't have the result of your get before you end the transaction.
If you are using Redis > 2.6.X, what you can do is use a Lua Script to create a function with you logic. See Redis Lua
This is exactly what I did to guarantee concurrency in my project.
Edit: Including a more complete example
You should create something like a PUBLISHNX script (not tested):
local shouldPublish = redis.call('SISMEMBER', KEYS[1], ARGV[1])
if shouldPublish == 0
redis.call('SADD', KEYS[1], ARGV[1])
redis.call('PUBLISH', ARGV[2], ARGV[3])
end
And you pass all the arguments necessary, channel, messageId, message, controlKey.
PS. Wei Li is right, you could accomplish the same result using WATCH and a loop for retrying in case of concurrency, but I still prefer using a Lua script.