How to Build a Custom Business Risk Control Component with Redis+Lua and Kotlin

This article explains why a business needs its own risk‑control (rate‑limit) component, compares open‑source options, and provides a complete Kotlin/Spring implementation using Redis Lua scripts, annotations, and AOP to enforce real‑time adjustable limits.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
How to Build a Custom Business Risk Control Component with Redis+Lua and Kotlin

Background

Our business heavily uses AI capabilities such as OCR and voice evaluation, which are costly, so we need to limit the number of times a user can invoke these services. Therefore a risk‑control (rate‑limit) component is required.

Why build our own?

Although many open‑source risk‑control libraries exist, they cannot satisfy our specific business requirements, which differ from generic solutions.

Other requirements

Support real‑time adjustment of limits.

Limits are often set initially but need to be changed later, so the system must apply updates immediately.

Design

To implement a simple business risk‑control component we need to define rules and a calling mechanism.

Risk‑control rules

Natural‑day count.

Natural‑hour count.

Combined natural‑day + natural‑hour count with rollback logic.

Counting method selection

Possible approaches:

MySQL + transaction (persistent but complex).

Redis + Lua (simple, supports atomic scripts).

MySQL/Redis + distributed transaction (requires locking, more complex).

Because we have no strict precision or persistence requirements, we choose redis+lua.

Implementation of call side

Define a generic entry point DetectManager.matchExceptionally(eventId, content) and invoke it from services.

// simplified Kotlin code
@Component
class DetectManager {
    fun matchExceptionally(eventId: String, content: String) {
        val rt = ruleService.match(eventId, content)
        if (!rt) {
            throw BaseException(ErrorCode.OPERATION_TOO_FREQUENT)
        }
    }
}

Service example:

// simplified Kotlin code
@Service
class OcrServiceImpl : OcrService {
    @Autowired
    private lateinit var detectManager: DetectManager

    override fun submitOcrTask(userId: String, imageUrl: String): String {
        detectManager.matchExceptionally("ocr", userId)
        // do ocr
    }
}

Annotation based solution

Define @Detect annotation and an AOP handler to evaluate SpEL expressions and invoke the risk‑control logic.

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
annotation class Detect(
    val eventId: String = "",
    val contentSpel: String = ""
)

Handler extracts method arguments as arg1, arg2…, evaluates the expression, and calls detectManager.matchExceptionally.

Testing

After adding @Detect to a method, the annotation values and expression are resolved correctly.

Annotation value retrieved successfully.

Expression parsed successfully.

Thus a simple risk‑control demo is completed; real‑world systems are far more complex.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendredisspringKotlinLuarisk control
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.