@Override
    public Stream<? extends Ticket> getSessionsWithAttributes(final Map<String, List<Object>> queryAttributes) {
        return redisModulesOperations
            .stream()
            .map(command -> {
                val criteria = new ArrayList<String>();
                queryAttributes.forEach((key, value) -> value.forEach(queryValue -> {
                    val escapedValue = isCipherExecutorEnabled()
                        ? digestIdentifier(queryValue.toString())
                        : StringUtils.replace(queryValue.toString(), "-", "\\-");
                    criteria.add(String.format("(%s" + (isCipherExecutorEnabled() ? " " : "_") + "*%s)", digestIdentifier(key), escapedValue));
                }));
                val query = String.format("(%s) @%s:%s", String.join("|", criteria),
                    RedisTicketDocument.FIELD_NAME_PREFIX, TicketGrantingTicket.PREFIX);
                LOGGER.debug("Executing search query [{}]", query);
                return command.search(SEARCH_INDEX_NAME, query)
                    .map(RedisTicketDocument::from)
                    .filter(document -> StringUtils.isNotBlank(document.json()))
                    .map(redisDoc -> {
                        val ticket = deserializeTicket(redisDoc.json(), redisDoc.type());
                        return decodeTicket(ticket);
                    })
                    .filter(ticket -> !ticket.isExpired());
            })
            .findFirst()
            .orElseGet(() -> (Stream<Ticket>) super.getSessionsWithAttributes(queryAttributes));
    }
Key-value ticket registry implementation that stores tickets in redis.

@author Misagh Moayyed
@author Jerome Leleu
@since 5.1.0
support/cas-server-support-redis-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/RedisTicketRegistry.java