国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 數(shù)據(jù)庫(kù) mysql教程 Finally Redis collections are iterable

Finally Redis collections are iterable

Jun 07, 2016 pm 04:35 PM
collections finally redis

Redis API for data access is usually limited, but very direct and straightforward. It is limited because it only allows to access data in a natural way, that is, in a data structure obvious way. Sorted sets are easy to access by score rang

Redis API for data access is usually limited, but very direct and straightforward.

It is limited because it only allows to access data in a natural way, that is, in a data structure obvious way. Sorted sets are easy to access by score ranges, while hashes by field name, and so forth.
This API “way” has profound effects on what Redis is and how users organize data into it, because an API that is data-obvious means fast operations, less code and less bugs in the implementation, but especially forcing the application layer to make meaningful choices: the database as a system in which you are responsible of organizing data in a way that makes sense in your application, versus a database as a magical object where you put data inside, and then it will be able to fetch and organize data for you in any format.

However most Redis data types, including the outer key-value shell if we want to consider it a data type for a moment (it is a dictionary after all), are collections of elements. The key-value space is a collection of keys mapped to values, as Sets are collections of unordered elements, and so forth.

In most application logic using Redis the idea is that you know what member is inside a collection, or at least you know what member you should test for existence. But life is not always that easy, and sometimes you need something more, that is, to scan the collection in order to retrieve all the elements inside. And yes, since this is a common need, we have commands like SMEMBERS or HGETALL, or even KEYS, in order to retrieve everything there is inside a collection, but those commands are always a last-resort kind of deal, because they are O(N) operations.

Your collection is very small? Fine, use SMEMBERS and you get Redis-alike performances anyway. Your collection is big? Don’t use O(N) commands if not for “debugging” purposes. A popular example is the misused KEYS command, source of troubles for non-experts, and top hit among the Redis slow log entries.

Black holes
===

The problem is that because of O(N) operations, Redis collections, (excluding Sorted Sets that can be accessed by rank, in ranges, and in many other different ways), tend to be black holes where you put things inside, and you can hardly explore them again.

And there are plenty of reasons to explore what is inside. For example garbage collection tasks, schema migration, or even fixing what is inside keys after an application bug corrupted some data.

What we really needed was an iterator. Pieter Noordhuis and I were very aware of this problem since the early days of Redis, but it was a major design challenge because traditionally the deal is, you want a data structure to be iterable? Well, this is going to be a sorted tree-like data structure, with the concept of previous and next element.

Instead most Redis data types are based on hash tables, and Redis hash tables are even of the most particular kind, as them automatically and incrementally resize, so sometime you even have two tables at the same time slowly exchanging elements from one to the other.

Hash tables are cool because they have a good memory efficiency, and the constant-time access property. What we use is power-of-two sized hash tables, with chaining for collision handling, and this has worked pretty well so far. An indirect indicator is that sorted sets, the only data structure we have that is based on a tree-alike structure (skip lists) is measurably slower than others once elements start to pile up. While Log(N) is small, with million of elements it starts to be a big enough number that cache misses summed together make a difference.

There was no easy way to say goodbye to hash tables.

However eventually Pieter applied one of the most powerful weapons the designer has in its hands: sacrifice, and send me a pull request for a new SCAN command.

The command was able to walk the key space incrementally, using a cursor that is returned back to the user after every call to SCAN, so it is a completely stateless affair. It is something like that:

redis 127.0.0.1:6379> flushall
OK
redis 127.0.0.1:6379> debug populate 33
OK
redis 127.0.0.1:6379> scan 0
1) "52"
2) 1) "key:29"
2) "key:13"
3) "key:9"
4) "key:12"
5) "key:28"
6) "key:30"
7) "key:26"
8) "key:14"
9) "key:21"
10) "key:20"
redis 127.0.0.1:6379> scan 52
1) "9"
2) 1) "key:16"
2) "key:31"
3) "key:3"
4) "key:0"
5) "key:32"
6) "key:17"
7) "key:24"
8) "key:8"
9) "key:15"
10) "key:11"

… and so forth until the returned cursor is 0 again …

This is possible because SCAN does not make big promises, hence the sacrifice: it guarantees to return all the elements that are in the collection from the start to the end of the iteration, at least one time.

This means, for example, that:

1) Elements may be returned multiple times.
2) Elements added during the iteration may be returned, or not, at random.

It turns out that this is a perfectly valid compromise, and that at application level you can almost always do what is needed to play well with this properties. Sometimes the operation you are doing on every element are simply safe to re-apply, some other times you can just put a flag in your (for example) Hash in order to mark it as processed, or a timestamp perhaps, and so forth.

Eventually merged
===

Pieter did an excellent work, but the pull request remained pending forever (more than one year), because it relied on a complex to understand implementation. Basically in order to guarantee the previous properties with tables that can change from one SCAN call to the other, Pieter used a cursor that is incremented inverting the bits, in order to count starting from the most significant bits first. This is why in the example you see the returned cursor jumping forward and backward.

This has different advantages, including the fact that it returns a small number of duplicates when possible (by checking less slots than a more naive implementation). Eventually I studied his code and tried to find a simpler algorithm with the same properties without success, so what I did is to document the algorithm. You can read the description here in the
dict.c file: https://github.com/antirez/redis/blob/unstable/src/dict.c#L663

After you do some whiteboard reasoning, it is not too hard to see how it works, but it is neither trivial, however it works definitely very well.

So with the code merged into unstable, I tried to generalize the implementation in order to work with all the other types in Redis that can be iterated this way, that are Hashes, Sets and Sorted Sets, in the form of additional commands named HSCAN, SSCAN, ZSCAN.

You may wonder why to have a ZSCAN. The reason is that while sorted sets are iterable in other ways, the specific properties of the SCAN iterator are not trivial to simulate by scanning elements by rank or score. Moreover sorted sets are internally implemented by a skiplist and an hash table, so we already had the hash table and to extend SCAN to sorted sets was trivial.

Patterns too!
===

SCAN and its variants can be used with the MATCH option in order to only return elements matching a pattern. I’m also implementing the TYPE option in order to only return keys of a specific type.

This is almost for free, since SCAN does not guarantees to return elements at all, so what happens is that it scans something like 10 buckets of the hash table per call (by default, you can change this) and later filters the output. Even if the return value contains no elements, you keep iterating as soon as the returned cursor is non-zero.

As you can see this is something you could do client-side as well, by matching the returned elements with a pattern, but it is much faster to do it server side given that is a very common pattern, and one that users are already used to because of the KEYS command. And it requires less I/O of course, if the pattern only matches a small number of elements.

This is an example:

edis 127.0.0.1:6379> scan 0 MATCH key:1*
1) "52"
2) 1) "key:13"
2) "key:12"
3) "key:14"
redis 127.0.0.1:6379> scan 52 MATCH key:1*
1) "9"
2) 1) "key:16"
2) "key:17"
3) "key:15"
4) "key:11"
redis 127.0.0.1:6379> scan 9 MATCH key:1*
1) "59"
2) 1) "key:10"
2) "key:1"
3) "key:18"
redis 127.0.0.1:6379> scan 59 MATCH key:1*
1) "0"
2) 1) "key:19"

In the last call the returned cursor is 0, so we ended the iteration.

Excited about it? I’ve good news, this is going to be back ported into 2.8 since it is completely self contained code so if it is broken, it does not affect other stuff. Well not just that, there are very big companies that are using SCAN for some time now, so I’m confident it’s pretty stable.

Enjoy iterating!

Discuss this blog post on Hacker News: https://news.ycombinator.com/item?id=6633091 Comments
本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)代碼編輯軟件(SublimeText3)

熱門話題

Laravel 教程
1601
29
PHP教程
1502
276
Laravel 最佳擴(kuò)展包推薦:2024 年必備工具 Laravel 最佳擴(kuò)展包推薦:2024 年必備工具 Apr 30, 2025 pm 02:18 PM

2024年必備的Laravel擴(kuò)展包包括:1.LaravelDebugbar,用于監(jiān)控和調(diào)試代碼;2.LaravelTelescope,提供詳細(xì)的應(yīng)用監(jiān)控;3.LaravelHorizon,管理Redis隊(duì)列任務(wù)。這些擴(kuò)展包能提升開發(fā)效率和應(yīng)用性能。

Laravel 環(huán)境搭建與基礎(chǔ)配置(Windows/Mac/Linux) Laravel 環(huán)境搭建與基礎(chǔ)配置(Windows/Mac/Linux) Apr 30, 2025 pm 02:27 PM

在不同操作系統(tǒng)上搭建Laravel環(huán)境的步驟如下:1.Windows:使用XAMPP安裝PHP和Composer,配置環(huán)境變量,安裝Laravel。2.Mac:使用Homebrew安裝PHP和Composer,安裝Laravel。3.Linux:使用Ubuntu更新系統(tǒng),安裝PHP和Composer,安裝Laravel。每個(gè)系統(tǒng)的具體命令和路徑有所不同,但核心步驟一致,確保順利搭建Laravel開發(fā)環(huán)境。

REDIS:與傳統(tǒng)數(shù)據(jù)庫(kù)服務(wù)器的比較 REDIS:與傳統(tǒng)數(shù)據(jù)庫(kù)服務(wù)器的比較 May 07, 2025 am 12:09 AM

Redis在高并發(fā)和低延遲場(chǎng)景下優(yōu)于傳統(tǒng)數(shù)據(jù)庫(kù),但不適合復(fù)雜查詢和事務(wù)處理。1.Redis使用內(nèi)存存儲(chǔ),讀寫速度快,適合高并發(fā)和低延遲需求。2.傳統(tǒng)數(shù)據(jù)庫(kù)基于磁盤,支持復(fù)雜查詢和事務(wù)處理,數(shù)據(jù)一致性和持久性強(qiáng)。3.Redis適用于作為傳統(tǒng)數(shù)據(jù)庫(kù)的補(bǔ)充或替代,但需根據(jù)具體業(yè)務(wù)需求選擇。

linux如何限制用戶資源?ulimit怎么配置? linux如何限制用戶資源?ulimit怎么配置? May 29, 2025 pm 11:09 PM

Linux系統(tǒng)通過ulimit命令限制用戶資源,防止資源過度占用。1.ulimit是shell內(nèi)置命令,可限制文件描述符數(shù)(-n)、內(nèi)存大?。?v)、線程數(shù)(-u)等,分為軟限制(當(dāng)前生效值)和硬限制(最高上限)。2.臨時(shí)修改直接使用ulimit命令,如ulimit-n2048,但僅對(duì)當(dāng)前會(huì)話有效。3.永久生效需修改/etc/security/limits.conf及PAM配置文件,并添加sessionrequiredpam_limits.so。4.systemd服務(wù)需在unit文件中設(shè)置Lim

Redis主要是數(shù)據(jù)庫(kù)嗎? Redis主要是數(shù)據(jù)庫(kù)嗎? May 05, 2025 am 12:07 AM

Redis主要是一個(gè)數(shù)據(jù)庫(kù),但它不僅僅是數(shù)據(jù)庫(kù)。1.作為數(shù)據(jù)庫(kù),Redis支持持久化,適合高性能需求。2.作為緩存,Redis提升應(yīng)用響應(yīng)速度。3.作為消息代理,Redis支持發(fā)布-訂閱模式,適用于實(shí)時(shí)通信。

REDIS:超越SQL- NOSQL的觀點(diǎn) REDIS:超越SQL- NOSQL的觀點(diǎn) May 08, 2025 am 12:25 AM

Redis超越SQL數(shù)據(jù)庫(kù)的原因在于其高性能和靈活性。1)Redis通過內(nèi)存存儲(chǔ)實(shí)現(xiàn)極快的讀寫速度。2)它支持多種數(shù)據(jù)結(jié)構(gòu),如列表和集合,適用于復(fù)雜數(shù)據(jù)處理。3)單線程模型簡(jiǎn)化開發(fā),但高并發(fā)時(shí)可能成瓶頸。

REDIS:揭示其目的和關(guān)鍵應(yīng)用程序 REDIS:揭示其目的和關(guān)鍵應(yīng)用程序 May 03, 2025 am 12:11 AM

Redisisanopen-Source,內(nèi)存內(nèi)部的庫(kù)雷斯塔氏菌,卡赫和梅斯吉級(jí),excellingInsPeedAndVersatory.itiswidelysusedforcaching,Real-Timeanalytics,Session Management,Session Managements,and sessighterboarderboarderboardobboardotoitsssupportfortfortfortfortfortfortfortfortorvortfortfortfortfortfortforvortfortforvortforvortforvortfortforvortforvortforvortforvortdatastherctuct anddatataCcessandcessanddataaCces

用PhpStudy搭建動(dòng)態(tài)PHP網(wǎng)站的步驟與示例 用PhpStudy搭建動(dòng)態(tài)PHP網(wǎng)站的步驟與示例 May 16, 2025 pm 07:54 PM

使用PhpStudy搭建動(dòng)態(tài)PHP網(wǎng)站的步驟包括:1.安裝PhpStudy并啟動(dòng)服務(wù);2.配置網(wǎng)站根目錄和數(shù)據(jù)庫(kù)連接;3.編寫PHP腳本生成動(dòng)態(tài)內(nèi)容;4.調(diào)試和優(yōu)化網(wǎng)站性能。通過這些步驟,你可以從零開始搭建一個(gè)功能完整的動(dòng)態(tài)PHP網(wǎng)站。

See all articles