summaryrefslogtreecommitdiff
path: root/src/bio.c
Commit message (Collapse)AuthorAgeFilesLines
* Implementing the WAITAOF command (issue #10505) (#11713)Slava Koyfman2023-03-141-57/+113
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Implementing the WAITAOF functionality which would allow the user to block until a specified number of Redises have fsynced all previous write commands to the AOF. Syntax: `WAITAOF <num_local> <num_replicas> <timeout>` Response: Array containing two elements: num_local, num_replicas num_local is always either 0 or 1 representing the local AOF on the master. num_replicas is the number of replicas that acknowledged the a replication offset of the last write being fsynced to the AOF. Returns an error when called on replicas, or when called with non-zero num_local on a master with AOF disabled, in all other cases the response just contains number of fsync copies. Main changes: * Added code to keep track of replication offsets that are confirmed to have been fsynced to disk. * Keep advancing master_repl_offset even when replication is disabled (and there's no replication backlog, only if there's an AOF enabled). This way we can use this command and it's mechanisms even when replication is disabled. * Extend REPLCONF ACK to `REPLCONF ACK <ofs> FACK <ofs>`, the FACK will be appended only if there's an AOF on the replica, and already ignored on old masters (thus backwards compatible) * WAIT now no longer wait for the replication offset after your last command, but rather the replication offset after your last write (or read command that caused propagation, e.g. lazy expiry). Unrelated changes: * WAIT command respects CLIENT_DENY_BLOCKING (not just CLIENT_MULTI) Implementation details: * Add an atomic var named `fsynced_reploff_pending` that's updated (usually by the bio thread) and later copied to the main `fsynced_reploff` variable (only if the AOF base file exists). I.e. during the initial AOF rewrite it will not be used as the fsynced offset since the AOF base is still missing. * Replace close+fsync bio job with new BIO_CLOSE_AOF (AOF specific) job that will also update fsync offset the field. * Handle all AOF jobs (BIO_CLOSE_AOF, BIO_AOF_FSYNC) in the same bio worker thread, to impose ordering on their execution. This solves a race condition where a job could set `fsynced_reploff_pending` to a higher value than another pending fsync job, resulting in indicating an offset for which parts of the data have not yet actually been fsynced. Imposing an ordering on the jobs guarantees that fsync jobs are executed in increasing order of replication offset. * Drain bio jobs when switching `appendfsync` to "always" This should prevent a write race between updates to `fsynced_reploff_pending` in the main thread (`flushAppendOnlyFile` when set to ALWAYS fsync), and those done in the bio thread. * Drain the pending fsync when starting over a new AOF to avoid race conditions with the previous AOF offsets overriding the new one (e.g. after switching to replicate from a new master). * Make sure to update the fsynced offset at the end of the initial AOF rewrite. a must in case there are no additional writes that trigger a periodic fsync, specifically for a replica that does a full sync. Limitations: It is possible to write a module and a Lua script that propagate to the AOF and doesn't propagate to the replication stream. see REDISMODULE_ARGV_NO_REPLICAS and luaRedisSetReplCommand. These features are incompatible with the WAITAOF command, and can result in two bad cases. The scenario is that the user executes command that only propagates to AOF, and then immediately issues a WAITAOF, and there's no further writes on the replication stream after that. 1. if the the last thing that happened on the replication stream is a PING (which increased the replication offset but won't trigger an fsync on the replica), then the client would hang forever (will wait for an fack that the replica will never send sine it doesn't trigger any fsyncs). 2. if the last thing that happened is a write command that got propagated properly, then WAITAOF will be released immediately, without waiting for an fsync (since the offset didn't change) Refactoring: * Plumbing to allow bio worker to handle multiple job types This introduces infrastructure necessary to allow BIO workers to not have a 1-1 mapping of worker to job-type. This allows in the future to assign multiple job types to a single worker, either as a performance/resource optimization, or as a way of enforcing ordering between specific classes of jobs. Co-authored-by: Oran Agra <oran@redislabs.com>
* Reclaim page cache of RDB file (#11248)Tian2023-02-121-1/+9
| | | | | | | | | | | | | | | | | | | | # Background The RDB file is usually generated and used once and seldom used again, but the content would reside in page cache until OS evicts it. A potential problem is that once the free memory exhausts, the OS have to reclaim some memory from page cache or swap anonymous page out, which may result in a jitters to the Redis service. Supposing an exact scenario, a high-capacity machine hosts many redis instances, and we're upgrading the Redis together. The page cache in host machine increases as RDBs are generated. Once the free memory drop into low watermark(which is more likely to happen in older Linux kernel like 3.10, before [watermark_scale_factor](https://lore.kernel.org/lkml/1455813719-2395-1-git-send-email-hannes@cmpxchg.org/) is introduced, the `low watermark` is linear to `min watermark`, and there'is not too much buffer space for `kswapd` to be wake up to reclaim memory), a `direct reclaim` happens, which means the process would stall to wait for memory allocation. # What the PR does The PR introduces a capability to reclaim the cache when the RDB is operated. Generally there're two cases, read and write the RDB. For read it's a little messy to address the incremental reclaim, so the reclaim is done in one go in background after the load is finished to avoid blocking the work thread. For write, incremental reclaim amortizes the work of reclaim so no need to put it into background, and the peak watermark of cache can be reduced in this way. Two cases are addresses specially, replication and restart, for both of which the cache is leveraged to speed up the processing, so the reclaim is postponed to a right time. To do this, a flag is added to`rdbSave` and `rdbLoad` to control whether the cache need to be kept, with the default value false. # Something deserve noting 1. Though `posix_fadvise` is the POSIX standard, but only few platform support it, e.g. Linux, FreeBSD 10.0. 2. In Linux `posix_fadvise` only take effect on writeback-ed pages, so a `sync`(or `fsync`, `fdatasync`) is needed to flush the dirty page before `posix_fadvise` if we reclaim write cache. # About test A unit test is added to verify the effect of `posix_fadvise`. In integration test overall cache increase is checked, as well as the cache backed by RDB as a specific TCL test is executed in isolated Github action job.
* Removing old redundant code from bio.c (#11136)Moti Cohen2022-08-261-39/+2
| | | | | | | | | * Remove redundant array bio_pending[]. Value at index i identically reflects the length of list bio_jobs[i]. Better use listLength() instead and discard this array. (no critical section issues to concern about). changed returned value of bioPendingJobsOfType() from "long long" to "long". Remove unused API. Maybe we will use this API later.
* fsync the old aof file when open a new INCR AOF (#11004)Binbin2022-07-251-18/+29
| | | | | | | | | | | | | | | | | | | | | In rewriteAppendOnlyFileBackground, after flushAppendOnlyFile(1), and before openNewIncrAofForAppend, we should call redis_fsync to fsync the aof file. Because we may open a new INCR AOF in openNewIncrAofForAppend, in the case of using everysec policy, the old AOF file may not be fsynced in time (or even at all). When using everysec, we don't want to pay the disk latency from the main thread, so we will do a background fsync. Adding a argument for bioCreateCloseJob, a `need_fsync` flag to indicate that a fsync is required before the file is closed. So we will fsync the old AOF file before we close it. A cleanup, we make union become a union, since the free_* args and the fd / fsync args are never used together. Co-authored-by: Oran Agra <oran@redislabs.com>
* Delete unused 'time' fields from struct bio_job (#9622)menwen2021-10-101-2/+0
| | | looks like this field was never actually used and the call to time() is excessive.
* Fix wrong check for aof fsync and handle aof fsync errno (#8751)Wang Yuan2021-04-111-1/+7
| | | | | | | | | | | The bio aof fsync fd may be closed by main thread (AOFRW done handler) and even possibly reused for another socket, pipe, or file. This can can an EBADF or EINVAL fsync error, which will lead to -MISCONF errors failing all writes. We just ignore these errno because aof fsync did not really fail. We handle errno when fsyncing aof in bio, so we could know the real reason when users get -MISCONF Errors writing to the AOF file error Issue created with #8419
* Handle remaining fsync errors (#8419)Wang Yuan2021-04-011-1/+11
| | | | | | | | In `aof.c`, we call fsync when stop aof, and now print a log to let user know that if fail. In `cluster.c`, we now return error, the calling function already handles these write errors. In `redis-cli.c`, users hope to save rdb, we now print a message if fsync failed. In `rio.c`, we now treat fsync errors like we do for write errors. In `server.c`, we try to fsync aof file when shutdown redis, we only can print one log if fail. In `bio.c`, if failing to fsync aof file, we will set `aof_bio_fsync_status` to error , and reject writing just like last writing aof error, moreover also set INFO command field `aof_last_write_status` to error.
* Cleanup key tracking documentation and table management (#8039)Madelyn Olson2020-12-231-24/+37
| | | Cleanup key tracking documentation, always cleanup the tracking table, and free the tracking table in an async manner when applicable.
* Backup keys to slots map and restore when fail to sync if diskless-load type ↵Wang Yuan2020-12-021-1/+1
| | | | | | | | | | | is swapdb in cluster mode (#8108) When replica diskless-load type is swapdb in cluster mode, we didn't backup keys to slots map, so we will lose keys to slots map if fail to sync. Now we backup keys to slots map at first, and restore it properly when fail. This commit includes a refactory/cleanup of the backups mechanism (moving it to db.c and re-structuring it a bit). Co-authored-by: Oran Agra <oran@redislabs.com>
* Make main thread killable so that it can be canceled at any time.WuYunlong2020-09-211-4/+1
| | | | | | | | Refine comment of makeThreadKillable(). This commit can be backported to 5.0, only if we also backport 8b70cb0. Co-authored-by: Oran Agra <oran@redislabs.com>
* bio: fix doFastMemoryTest.WuYunlong2020-09-161-1/+2
| | | | | | | If one thread got SIGSEGV, function sigsegvHandler() would be triggered, it would call bioKillThreads(). But call pthread_cancel() to cancel itself would make it block. Also note that if SIGSEGV is caught by bio thread, it should kill the main thread in order to give a positive report.
* Fix unidentical function declaration in bio.c. lazyfree.c: ↵Muhammad Zahalqa2020-08-111-1/+1
| | | | lazyfreeFreeSlotsMapFromBioThread (#7228)
* Support setcpuaffinity on linux/bsdzhenwei pi2020-05-021-0/+2
| | | | | | | | | | | | | | | | | | | | | | | Currently, there are several types of threads/child processes of a redis server. Sometimes we need deeply optimise the performance of redis, so we would like to isolate threads/processes. There were some discussion about cpu affinity cases in the issue: https://github.com/antirez/redis/issues/2863 So implement cpu affinity setting by redis.conf in this patch, then we can config server_cpulist/bio_cpulist/aof_rewrite_cpulist/ bgsave_cpulist by cpu list. Examples of cpulist in redis.conf: server_cpulist 0-7:2 means cpu affinity 0,2,4,6 bio_cpulist 1,3 means cpu affinity 1,3 aof_rewrite_cpulist 8-11 means cpu affinity 8,9,10,11 bgsave_cpulist 1,10-11 means cpu affinity 1,10,11 Test on linux/freebsd, both work fine. Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
* fix for crash during panic before all threads are upDave-in-lafayette2020-04-201-1/+1
| | | If there's a panic before all threads have been started (say, if file descriptor 0 is closed at exec), the panic response will crash here again.
* Threaded IO: set thread name for redis-serverzhenwei pi2020-04-181-0/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Set thread name for each thread of redis-server, this helps us to monitor the utilization and optimise the performance. And suggested-by Salvatore, implement this feature for multi platforms. Currently support linux and bsd, ignore other OS. An exmaple on Linux: # top -d 5 -p `pidof redis-server ` -H PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3682671 root 20 0 227744 8248 3836 R 99.2 0.0 0:19.53 redis-server 3682677 root 20 0 227744 8248 3836 S 26.4 0.0 0:04.15 io_thd_3 3682675 root 20 0 227744 8248 3836 S 23.6 0.0 0:03.98 io_thd_1 3682676 root 20 0 227744 8248 3836 S 23.6 0.0 0:03.97 io_thd_2 3682672 root 20 0 227744 8248 3836 S 0.2 0.0 0:00.02 bio_close_file 3682673 root 20 0 227744 8248 3836 S 0.2 0.0 0:00.02 bio_aof_fsync 3682674 root 20 0 227744 8248 3836 S 0.0 0.0 0:00.00 bio_lazy_free 3682678 root 20 0 227744 8248 3836 S 0.0 0.0 0:00.00 jemalloc_bg_thd 3682682 root 20 0 227744 8248 3836 S 0.0 0.0 0:00.00 jemalloc_bg_thd 3682683 root 20 0 227744 8248 3836 S 0.0 0.0 0:00.00 jemalloc_bg_thd 3682684 root 20 0 227744 8248 3836 S 0.0 0.0 0:00.00 jemalloc_bg_thd 3682685 root 20 0 227744 8248 3836 S 0.0 0.0 0:00.00 jemalloc_bg_thd 3682687 root 20 0 227744 8248 3836 S 0.0 0.0 0:00.00 jemalloc_bg_thd Another exmaple on FreeBSD-12.1: PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU COMMAND 5212 root 100 0 48M 7280K CPU2 2 0:26 99.52% redis-server{redis-server} 5212 root 38 0 48M 7280K umtxn 4 0:06 26.94% redis-server{io_thd_3} 5212 root 36 0 48M 7280K umtxn 6 0:06 26.84% redis-server{io_thd_1} 5212 root 39 0 48M 7280K umtxn 1 0:06 25.30% redis-server{io_thd_2} 5212 root 20 0 48M 7280K uwait 3 0:00 0.00% redis-server{redis-server} 5212 root 21 0 48M 7280K uwait 2 0:00 0.00% redis-server{bio_close_file} 5212 root 21 0 48M 7280K uwait 3 0:00 0.00% redis-server{bio_aof_fsync} 5212 root 21 0 48M 7280K uwait 0 0:00 0.00% redis-server{bio_lazy_free} Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
* Fix typo in design comment of bio.c.antirez2018-10-051-1/+1
|
* bio: fix bioWaitStepOfType.youjiali19952018-09-051-3/+3
|
* rdb: incremental fsync when redis saves rdbzhaozhao.zz2018-03-161-1/+1
|
* Lazyfree: ability to free whole DBs in background.antirez2015-10-011-1/+12
|
* Lazyfree: keep count of objects to free.antirez2015-10-011-1/+2
|
* Threaded lazyfree WIP #1.antirez2015-10-011-0/+2
|
* bio.c: new API bioWaitStepOfType().antirez2015-10-011-4/+31
|
* RDMF: more names updated.antirez2015-07-271-11/+11
|
* RDMF: More consistent define names.antirez2015-07-271-6/+6
|
* RDMF: redisLog -> serverLog.antirez2015-07-261-5/+5
|
* RDMF (Redis/Disque merge friendlyness) refactoring WIP 1.antirez2015-07-261-1/+1
|
* Check bio.c job type at thread startup.antirez2015-03-301-0/+7
| | | | | Another one just to avoid a warning. Slightly more defensive code anyway.
* Fixed many typos.guiquanz2013-01-191-1/+1
|
* Make bio.c threads killable ASAP if needed.antirez2012-11-221-50/+23
| | | | | | | We use this new bio.c feature in order to stop our I/O threads if there is a memory test to do on crash. In this case we don't want anything else than the main thread to run, otherwise the other threads may mess with the heap and the memory test will report a false positive.
* BSD license added to every C source and header file.antirez2012-11-081-0/+30
|
* Mask SIGALRM everything but in the main thread.antirez2012-03-271-0/+9
| | | | | This is required to ensure that the signal will be delivered to the main thread when the watchdog timer expires.
* Comment out things in bio.c that are currently not useful but that may be ↵antirez2011-09-191-0/+6
| | | | useful in the future.
* use aof_fsync wrapper instead of fsync(2) in bio.cantirez2011-09-161-1/+1
|
* REDIS_BIO_AOF_FSYNC implementedantirez2011-09-151-0/+2
|
* fixed a problem in bioOlderJobType() when there are no jobs of the specified ↵antirez2011-09-151-0/+4
| | | | type. Now the function returns 0 when this happens.
* some more comment about bio.c designantirez2011-09-151-0/+4
|
* Remove backgroud jobs from the queue only when the processing was completed, ↵antirez2011-09-151-1/+1
| | | | and not just started.
* Use a different thread for every different type of background jobantirez2011-09-151-36/+62
|
* Better comments for bioWaitPendingJobsLEantirez2011-09-151-1/+9
|
* Background I/O library enhanced so that the main thread can query for the ↵antirez2011-09-151-1/+46
| | | | number of pending jobs of the specified type.
* make bio_list static as wellantirez2011-09-131-1/+1
|
* debug message removedantirez2011-09-131-1/+0
|
* use pthread_cond_signal() to make sure the background thread will process ↵antirez2011-09-131-0/+1
| | | | the job.
* typo fixed in bio.cantirez2011-09-131-1/+2
|
* bio.c typos fixes to make it compileantirez2011-09-131-4/+9
|
* bio.o added to redis-server objectsantirez2011-09-131-0/+107