As far as I understand, containsKey on distributed cache performs a GetKeyValueCommand (which may be executed remotedly) and checks if the result was null.
This results in loading the whole entry, which may be expensive when dealing with large entries.
In our system we introduced a KeyExistsTask implementing DistributedCallable, which we submit with distributed execution framework. This task performs cache.containsKey on keys local node avoiding unnecessary transfer of possibly large amount of data.
In our case this brought a significant improvement of containsKey operation.
Best regards,
Mikolaj