第一次在PyPi上傳開源工程,各種問題搞的相當坎坷,先貼個github地址
github: https://github.com/524243642/ratel
PyPi:https://pypi.org/project/ratel/
本工程參考redis的開源工程(redis源代碼十分優秀)
編寫這個庫的緣由是我在編寫一個工程化的策略的模塊的時候碰到一個棘手的問題,先來描述一下我碰到的問題
數據結構需要滿足的條件爲
1.能夠獲取分數最小的對象,在此基礎上進行update操作進行分數的更新(分數可能重複,key不重複)
2.能夠根據key獲取對象,滿足一,定條件後進行update操作對象分數
3.根據key刪除對象
以下介紹各種方案:
1)純列表
根據key獲取對象需要遍歷搜索,時間複雜度爲O(n)),獲取分數最小的對象需要排序,時間複雜度爲O(nlogn)
2)字典
根據key獲取對象時間複雜度爲O(1),獲取分數最小的對象需要排序,時間複雜度爲O(nlogn)
3)優先隊列
優先隊列可以滿足分數可能重複,key不重複的場景,能夠滿足條件1,目前python內置priority queue無法滿足條件2和條件3
4)PyPi跳錶
https://pypi.org/project/python-skiplist/
目前這個實現底層採用c語言代碼,比較高效
但是這個列表是根據key進行排序,如果把score作爲key,則不支持重複分數插入,(對於這個問題,redis就做的比較全面,以很精簡的結構支持很多業務型操作)
5)redis zset
能夠支持各種複雜的業務操作,包括根據key查詢操作能夠維持在O(1)的複雜度,但是在PyPi上沒有相應的實現
redis zset具體數據結構分析詳見
https://blog.csdn.net/u012748735/article/details/82897479
6)python zset
樓主目前上傳到PyPi上的redis zset的Python實現,集成了coverage和ci檢測,目前能夠穩定運行
api採用內置對象的原因是因爲,分數可能會更改,方便對象的回溯行爲
由於目前python list是鏈表的實現,爲了增強性能,python zset 採用numpy array的內置對象來實現快速的下標訪問 ,(2018-12-23)目前採用cython實現
經過benchmark實際測試,性能在數據量大的時候比較有優勢
目前支持的api
ZsetObj Operations | Average Case |
---|---|
zadd | O(log N) |
zincrby | O(log N) |
zrem | O(log N) |
zscore | O(1) |
zcard | O(1) |
zrange | O(log N) |
zrevrange | O(log N) |
zfloor | O(log N) |
zlower | O(log N) |
zrange_by_score | O(log N) |
zrevrange_by_score | O(log N) |
如果有需要擴展的api,通過郵箱聯繫博主進行增強
藉此來幫助有需要的朋友,由於是第一次搞這種工程,難免有什麼不妥的地方,如果各位在使用過程中有什麼疑問或者問題,歡迎大家批評指正(勇提pull request),大家共同進步
版本更新
2018-11-28 0.2.19 純python實現版,insert 1w/0.5s
2018-12-04 0.3.3 cython實現,insert 10w/0.5s,性能提升一個數量級
2018-12-23 支持zfloor,zlower支持一致性hash所需要的查詢方式
2019-01-23 接入shields.io
2019-04-25 支持zrange_by_score,zrevrange_by_score
博主郵箱:
[email protected]
附錄
eq:c python api 和cython
https://www.2cto.com/kf/201606/517257.html
使用c python api寫數據結構比較麻煩,需要關注引用計數,cython編寫需要掌握cython優化語法,通過編寫pyx,然後調用so
eq:c python各種架構
https://www.jianshu.com/p/fc5025094912