Use redission implement distributed semaphores and some pit encountered
1, connected RedissonClient
Config config = Config.fromJSON(redisCfgFile); RedissonClient redissonClient = Redisson.create(config);
Creating RedissionClient, created using the json form.
redis is as follows:
{ "singleServerConfig":{ "idleConnectionTimeout":10000, "pingTimeout":1000, "connectTimeout":10000, "timeout":6000, "retryAttempts":3, "retryInterval":1500, "reconnectionTimeout":3000, "failedAttempts":3, "password":"xxxxx", "subscriptionsPerConnection":5, "clientName":null, "address":"redis://xxxx:000", "subscriptionConnectionMinimumIdleSize":1, "subscriptionConnectionPoolSize":50, "connectionMinimumIdleSize":32, "connectionPoolSize":64, "database":0 }, "threads":0, "nettyThreads":0, "codec":{ "class":"org.redisson.codec.JsonJacksonCodec" }, "transportMode":"NIO" }
Configuration Description: https://yq.aliyun.com/articles/551640?spm=a2c4e.11153940.0.0.3cc221bavS8pf3 (Reference)
Encountered pit:
1, disconnect
redis use 5.0, redission use 3.10.7, often appear disconnected from the client and server problems
Tracing problem, the online version redis decreased, from 5.0 to> 4.0, disconnection does not occur. But redission not supported to disconnect and reconnect, use scheduled tasks to the timing of ping server, disconnect the manual reconnection.
2, the main switch can not be automatically reconnect
public static void init() { SCHEDULED_EXECUTOR_SERVICE.scheduleWithFixedDelay(() -> { if (RUNNING) { try { NodesGroup nodesGroup = redissonClient.getNodesGroup(); Collection<Node> allNodes = nodesGroup.getNodes(); for (Node n : allNodes) { boolean ping = n.ping(); if (!ping) { //ping不通reload client reload (); } } } the catch (Exception E) { // throws an exception Client reload reload (); } } }, 0,. 5 , TimeUnit.SECONDS); }
3, the line often timed out
Modify the configuration file timeout 3000 -> 6000, because there is a regular task 5s in ping server, so set slightly larger, it will not appear.
2, a distributed semaphore implemented using redission
Redisson carrying a RPermitExpirableSemaphore (distributed semaphore has an expiration date)
The official explanation:
Providing an amount of the release time parameter signals for each of the application objects, each license may be their own id to identify, and can be released their id. The license id 128b is a random number. At the same time this distributed semaphore In non-equity model, so is not possible to predict the order of application.
Specific achieve the following:
Apply for a permit
/ ** * @param semaphoreName semaphore IDs * @param identify the person who acquired acquireId * @param total limit * @return int 0- success, others - failed * @Description: specify the name and the total acquisition semaphore * / public static int acquireSemaphore (semaphoreName String, String acquireId, Long limit) { the try { RedissonClient Client = RedisUtils.getRedissonClient (); RPermitExpirableSemaphore semaphore = client.getPermitExpirableSemaphore (semaphoreName); semaphore.trySetPermits (( int ) limit); // Each application time semaphores, expire life SEMAPHORE_LIFE_EXPIRE second semaphore semaphore.expire (SEMAPHORE_LIFE_EXPIRE, TimeUnit.SECONDS); // number of attempts the init int Time = 0 ; the while (MAX_TRY_ACQUIRE_TIME> Time) { // attempts to acquire a semaphore String = permitId semaphore.tryAcquire (getSemaphoreLifeExpire (), getSemaphoreAcquireExpire (), TimeUnit.MILLISECONDS); // Get semaphore failed IF ( null == permitId) { Time ++; Continue ; } // get the semaphore success, mapping between acquireId and permitId of IF (! RedisUtils.hset (getMapName (semaphoreName), acquireId, permitId, getSemaphoreAcquireExpire (), TimeUnit.MILLISECONDS)) { // if it fails to release resources semaphore.release (permitId); return acquireError (); } return 0 ; } } the catch (Exception E) { e.printStackTrace (); log.error ( "Exception for semaphoreName = {}, {} = acquireId, MSG = {}" , semaphoreName, acquireId, e.getMessage ()); } return acquireError(); }
The application of the license id and acquireId into hash structure, make a map, because of the need to release this license id resources.
Release Semaphore
/ ** * @param semaphoreName semaphore IDs * @param acquireId obtain identity's * @Description: release signal corresponding to the amount * @return : int 0 Success 1 Failure (time-out errors might not be successful release) * @author: chi.zhang * @date: 2020/02/19 * / public static int ReleaseSemaphore (semaphoreName String, String acquireId) { the try { RedissonClient Client = RedisUtils.getRedissonClient (); RPermitExpirableSemaphore semaphore = client.getPermitExpirableSemaphore (semaphoreName); // The mapping relationships to find permitId PermitId = String RedisUtils.hgetStr (getMapName (semaphoreName), acquireId); IF (StringUtils.isNotEmpty (permitId)) { // may be released, so use tryRelease IF (semaphore.tryRelease (permitId)) { RedisUtils.hdel (getMapName ( semaphoreName), acquireId); } } the else { log.error ( "distributed release semaphore failed, semaphoreName: {}, {} permitId" , semaphoreName, permitId); return releaseError (); } } the catch (Exception E) { e.printStackTrace (); lOG.error ("exception for semaphoreName={}, acquireId={}, msg={}", semaphoreName, acquireId, e.getMessage()); return releaseError(); } return 0; }