{"id":21064024,"url":"https://github.com/luochen1990/ring_redis","last_synced_at":"2025-05-16T02:32:16.678Z","repository":{"id":15879554,"uuid":"18620607","full_name":"luochen1990/ring_redis","owner":"luochen1990","description":"a python package in pure python; a lightweight, high available \u0026 extensible cache solution using redis","archived":false,"fork":false,"pushed_at":"2014-09-04T12:55:29.000Z","size":168,"stargazers_count":18,"open_issues_count":1,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-19T19:53:35.008Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"Leelow/upper-body-clustering","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luochen1990.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-04-10T02:08:13.000Z","updated_at":"2021-04-05T15:15:24.000Z","dependencies_parsed_at":"2022-09-09T12:41:18.618Z","dependency_job_id":null,"html_url":"https://github.com/luochen1990/ring_redis","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luochen1990%2Fring_redis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luochen1990%2Fring_redis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luochen1990%2Fring_redis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luochen1990%2Fring_redis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luochen1990","download_url":"https://codeload.github.com/luochen1990/ring_redis/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254456039,"owners_count":22074085,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T17:48:02.623Z","updated_at":"2025-05-16T02:32:11.668Z","avatar_url":"https://github.com/luochen1990.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"RING REDIS\n===\n\nWhat for:\n---\n\nI want a lightweight, High Available \u0026 Extensible cache solution using redis, but nutcracker is too heavy for a system with only 2 or 3 application servers and 2 or 3 redis instances. and there isnt a good enough implementation of consistant hash using pure python. so I wrote this. I used it in 2 project and they are running well till now when half a year passed. so I shared it for people who have the same requirement.\n\nFeatures:\n---\n\n- lightweight \u0026 pure python solution\n- auto eject \u0026 rediscover redis nodes\n- O(log(slice_number)) time complexity for a consistant hash calculation. (slice_number = max(2000, 200 * node_number))\n- O(slice_number * log(slice_number)) time complexity for hash ring rebuilding.\n- use O(slice_number) memory space always.\n\nAPI list:\n---\n\n- `redis_dict(redis_confs, prefix='', key=str, expire=None, on_fail=None, on_node_ejected=None, on_node_rediscovered=None, retry_ratio=1e-2, hash_function=crc32)`: construct a redis_dict instance, which can be used as a normal python dict\n- `some_redis_dict_instance.visit_redis(cmd, k, args)`: visit lower level redis apis\n- `some_redis_dict_instance.get_entry(k)`: return the really redis entry of k\n- `some_redis_dict_instance.alive_hash(redis_entry)`: return the node name for redis_entry via alive_hash\n- `some_redis_dict_instance.total_hash(redis_entry)`: return the node name for redis_entry via total_hash\n- `len(some_redis_dict_instance.alive_hash)`: return the alive nodes number\n\nInstall\n---\n\n### via pip\n```shell\npip install ring_redis\n```\n\n### via source code\n```shell\ncd path/to/ring_redis\npython setup.py install\n```\n\nHow to use:\n---\n\n```python\n################### your redis configuration #####################\n\nREDIS_CONF = {\n\t'group0' : {\n\t\t'node0': {\n\t\t\t'capacity': 50 * 1024 ** 2,\n\t\t\t'connection': {\n\t\t\t\t'host' : '192.168.230.45',\n\t\t\t\t'port' : 15061,\n\t\t\t\t'db': 0,\n\t\t\t\t'socket_timeout': 5e-3,\n\t\t\t},\n\t\t},\n\t\t'node1': {\n\t\t\t'capacity': 50 * 1024 ** 2,\n\t\t\t'connection': {\n\t\t\t\t'host' : '192.168.230.46',\n\t\t\t\t'port' : 15061,\n\t\t\t\t'db': 0,\n\t\t\t\t'socket_timeout': 5e-3,\n\t\t\t},\n\t\t},\n\t},\n}\n\n############################ useage ##############################\n\nfrom ring_redis import redis_dict\n\ntest = redis_dict(REDIS_CONF['group0'], prefix='test.', expire=20)\n\ntest['a'] = 'abc'\nprint(\"test['a'] : %s\" % (test['a']))\n\nprint(\"len(test) : %s\" % (len(test)))\nprint(\"test.keys() : %s\" % (test.keys()[:100]))\nprint(\"'a' in test? : %s\" % ('a' in test))\nprint(\"'b' in test? : %s\" % ('b' in test))\n\nprint(\"test.visit_redis('incr', 'x', 1) : %s\" % (test.visit_redis('incr', 'x', 1)))\nprint(\"test.get_entry('x') : %s\" % (test.get_entry('x')))\nprint(\"test.total_hash(test.get_entry('x')) : %s\" % (test.total_hash(test.get_entry('x'))))\nprint(\"test.alive_hash(test.get_entry('x')) : %s\" % (test.alive_hash(test.get_entry('x'))))\n```\n\nNotice:\n---\n\n- The really redis entry equals to the dict key **only if** `prefix + key(dict_key) == redis_entry`\n- The configuration field 'socket_timeout' in REDIS_CONF **should be choosed carefully**, do some test yourself to findout the expected time(in seconds, depending on your network delay \u0026 bandwidth) needed for your biggest data case.\n- Python built-in function hash is neither consistant nor equally distributed, so **don't use it** as hash_function.\n- If non instance of the redis cluster available, exception `RedisClusterUnavailable` will be raised, you should pass `on_fail` as argument of redis_dict constructor or catch this exception to **handler this situation yourself**.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluochen1990%2Fring_redis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluochen1990%2Fring_redis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluochen1990%2Fring_redis/lists"}