|
| 1 | +# Bucket4j PostgreSQL Cache Module |
| 2 | + |
| 3 | +This module provides PostgreSQL database support for Bucket4j rate limiting with Spring Boot. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The `cache-postgresql` module integrates Bucket4j with PostgreSQL, allowing you to store rate limit data in a PostgreSQL relational database. This is useful for distributed systems that already use PostgreSQL and want to leverage it for centralized rate limiting. |
| 8 | + |
| 9 | +## Features |
| 10 | + |
| 11 | +- **Synchronous Cache Access**: Provides synchronous rate limit token bucket operations |
| 12 | +- **JDBC-based**: Uses Bucket4j's JDBC proxy manager for PostgreSQL connectivity |
| 13 | +- **Spring Boot Auto-Configuration**: Automatic configuration when dependencies are present |
| 14 | +- **Event Publishing**: Publishes cache update events to Spring's ApplicationEventPublisher |
| 15 | +- **Configuration Caching**: Optional caching of Bucket4j configuration |
| 16 | + |
| 17 | +## Dependencies |
| 18 | + |
| 19 | +The module requires the following: |
| 20 | + |
| 21 | +- `spring-boot-starter-data-jpa`: For JPA support (optional) |
| 22 | +- `postgresql`: PostgreSQL JDBC driver |
| 23 | +- `bucket4j_jdk17-jdbc`: Bucket4j JDBC support |
| 24 | + |
| 25 | +## Configuration |
| 26 | + |
| 27 | +To use the PostgreSQL cache module, add the following to your `application.properties` or `application.yml`: |
| 28 | + |
| 29 | +```properties |
| 30 | +bucket4j.enabled=true |
| 31 | +bucket4j.cache-type=postgresql |
| 32 | +``` |
| 33 | + |
| 34 | +### Database Setup |
| 35 | + |
| 36 | +Before using the PostgreSQL cache, you need to create the necessary table for storing bucket tokens. Bucket4j uses a standard schema for JDBC storage. |
| 37 | + |
| 38 | +Create the table with the following SQL: |
| 39 | + |
| 40 | +```sql |
| 41 | +CREATE TABLE IF NOT EXISTS bucket ( |
| 42 | + id VARCHAR(20) PRIMARY KEY, |
| 43 | + state BYTEA, |
| 44 | + expires_at BIGINT, |
| 45 | + explicit_lock BIGINT); |
| 46 | + |
| 47 | +CREATE INDEX IF NOT EXISTS idx_bucket4j_id ON bucket(id); |
| 48 | +``` |
| 49 | + |
| 50 | +## Components |
| 51 | + |
| 52 | +### PostgreSQLCacheResolver |
| 53 | + |
| 54 | +Implements `SyncCacheResolver` and uses Bucket4j's `JdbcProxyManager` to manage rate limit buckets through JDBC connections. |
| 55 | + |
| 56 | +**Key Features:** |
| 57 | +- Synchronous access to rate limit tokens |
| 58 | +- Automatic connection pooling through DataSource |
| 59 | +- Direct integration with PostgreSQL via JDBC |
| 60 | + |
| 61 | +### PostgreSQLCacheManager |
| 62 | + |
| 63 | +Implements `CacheManager` for managing cache entries in the PostgreSQL database. |
| 64 | + |
| 65 | +**Key Methods:** |
| 66 | +- `getValue(K key)`: Retrieves cached values from the database |
| 67 | +- `setValue(K key, V value)`: Stores or updates values in the database using PostgreSQL's `ON CONFLICT` clause |
| 68 | + |
| 69 | +### PostgreSQLCacheListener |
| 70 | + |
| 71 | +Listens to cache updates and publishes `CacheUpdateEvent` to the Spring ApplicationEventPublisher. |
| 72 | + |
| 73 | +### PostgreSQLBucket4jConfiguration |
| 74 | + |
| 75 | +Spring Boot auto-configuration class that: |
| 76 | +- Checks if Bucket4j is enabled |
| 77 | +- Validates DataSource availability |
| 78 | +- Registers the `PostgreSQLCacheResolver` bean |
| 79 | +- Optionally registers configuration cache manager |
| 80 | +- Registers cache listener for event publishing |
| 81 | + |
| 82 | +## Usage Example |
| 83 | + |
| 84 | +```java |
| 85 | +@RestController |
| 86 | +@RequestMapping("/api") |
| 87 | +public class MyController { |
| 88 | + |
| 89 | + @GetMapping("/data") |
| 90 | + @Bucket4j(bucketName = "main", capacityDescription = "10 requests per minute") |
| 91 | + public ResponseEntity<String> getData() { |
| 92 | + return ResponseEntity.ok("Hello World"); |
| 93 | + } |
| 94 | +} |
| 95 | +``` |
| 96 | + |
| 97 | +## Configuration Properties |
| 98 | + |
| 99 | +The following properties can be configured in `application.properties`: |
| 100 | + |
| 101 | +```properties |
| 102 | +# Enable Bucket4j |
| 103 | +bucket4j.enabled=true |
| 104 | + |
| 105 | +# Set cache type to PostgreSQL |
| 106 | +bucket4j.cache-type=postgresql |
| 107 | + |
| 108 | +# Optional: Cache configuration in PostgreSQL |
| 109 | +bucket4j.filter-config-cache-enabled=true |
| 110 | + |
| 111 | +# DataSource configuration (Spring Boot standard) |
| 112 | +spring.datasource.url=jdbc:postgresql://localhost:5432/mydb |
| 113 | +spring.datasource.username=postgres |
| 114 | +spring.datasource.password=password |
| 115 | +spring.datasource.driver-class-name=org.postgresql.Driver |
| 116 | +``` |
| 117 | + |
| 118 | +## Performance Considerations |
| 119 | + |
| 120 | +1. **Connection Pooling**: Ensure proper HikariCP (or other connection pool) configuration for optimal performance |
| 121 | +2. **Table Indexing**: The `idx_bucket4j_tokens_id` index improves lookup performance |
| 122 | +3. **Network Latency**: PostgreSQL-based rate limiting incurs network round-trip time, making it slower than in-memory solutions |
| 123 | +4. **Distributed Systems**: Best suited for distributed systems where a centralized database is already in use |
| 124 | + |
| 125 | +## Advantages |
| 126 | + |
| 127 | +- **Centralized Rate Limiting**: All instances share the same rate limit state |
| 128 | +- **Data Persistence**: Rate limit data survives application restarts |
| 129 | +- **Simplicity**: Leverages existing PostgreSQL infrastructure |
| 130 | +- **Scalability**: Works well in containerized and cloud environments |
| 131 | + |
| 132 | +## Limitations |
| 133 | + |
| 134 | +- **Performance**: Slower than in-memory cache solutions due to database I/O |
| 135 | +- **Synchronous Only**: This module only provides synchronous cache access |
| 136 | +- **Database Dependency**: Requires PostgreSQL to be available and operational |
| 137 | + |
| 138 | +## Related Modules |
| 139 | + |
| 140 | +- `cache-jcache`: JCache (JSR-107) implementation |
| 141 | +- `cache-redis-lettuce`: Redis Lettuce driver support |
| 142 | +- `cache-redis-jedis`: Redis Jedis driver support |
| 143 | +- `cache-redis-redisson`: Redis Redisson driver support |
| 144 | +- `cache-hazelcast`: Hazelcast distributed cache support |
| 145 | +- `cache-infinispan`: Infinispan cache support |
| 146 | + |
| 147 | +## License |
| 148 | + |
| 149 | +Apache License 2.0 |
| 150 | + |
0 commit comments