求助:一個(gè)公司考核的數(shù)據(jù)庫項(xiàng)目,里面包含多個(gè)多對多的關(guān)系,如一個(gè)工廠包含多個(gè) KPI,一個(gè) KPI 也對應(yīng)多個(gè)工廠;一個(gè)過程分工包含多個(gè)二級流程,每個(gè)二級流程也對應(yīng)多個(gè)過程分工;每個(gè)二級流程對應(yīng)多個(gè)三級流程,每個(gè)三級流程也對應(yīng)多個(gè)二級流程等等。這種考核系統(tǒng)的數(shù)據(jù)庫設(shè)計(jì),是否將每個(gè)多對多的關(guān)系都增加一個(gè)中間表即可呢?還有什么更好的解決多對多關(guān)系的設(shè)計(jì)方法嗎?
謝謝!
現(xiàn)在有個(gè)業(yè)務(wù)數(shù)據(jù)表 A,大概有一百多個(gè)字段,頁面表單也呈現(xiàn)的是這一百多個(gè)字段。 要求:每次用戶修改了其中的字段,都要發(fā)送提醒給管理員。管理員要知道修改了哪些字段。
這種是不是要多加一百多個(gè)字段標(biāo)識是否修改過?
數(shù)據(jù)庫:mysql
現(xiàn)在想用 django 寫一個(gè) web,用哪個(gè)版本比較好一些。之前接觸過,1.x 的。現(xiàn)在我看都更新到 3.x 了
想集成一個(gè)在網(wǎng)站里面,有用過的分享一下。謝謝
用戶上傳文件( VUE )-> 存儲相關(guān)信息至數(shù)據(jù)庫 -> 計(jì)算文件其他相關(guān)參數(shù)如(size, length(語音時(shí)長)) -> 更新數(shù)據(jù)庫數(shù)據(jù)庫 Model: FileField, Size, Length 我的問題是: 因?yàn)楸仨毜扔脩魧⑽募鞯侥夸浵聲r(shí),服務(wù)器端才能用得到的文件來計(jì)算相關(guān)參數(shù),然后更新數(shù)據(jù)庫 如何得知文件已經(jīng)傳好了? 并立即更新數(shù)據(jù)庫相關(guān)字段 (因?yàn)橐婚_始文件并沒有達(dá)到服務(wù)器端,所以一開始設(shè)置一個(gè) default 值給 size, length; 等計(jì)算好了,再更新)
目前封裝了 ansible playbook api,執(zhí)行 playbook 后返回結(jié)果類似如下 { "ok": { "include_tasks": "OK" }, "failed": { "獲取 XX 信息[192.168.21.1]": "Unable to gather facts for non-existing VM " }, "unreachable": {}, "skipped": {}, "status": {}, "programbug": {}, "virtual_ip": "192.168.21.1", "task_id": "add_virtual-1590664169876" }
現(xiàn)在的需求是,根據(jù)執(zhí)行每個(gè) playbook,寫入一個(gè) log 文件,到時(shí)再通過 websocket 進(jìn)行獲取這個(gè)日志文件,實(shí)時(shí)再前端顯示每個(gè) task 結(jié)果,而不必等到全部執(zhí)行完再獲取結(jié)果,因?yàn)橛袝r(shí)候一個(gè) playbook 包含了好幾個(gè) task 的。
要實(shí)現(xiàn)這個(gè)功能應(yīng)該怎么搞法。
或者各位大佬在實(shí)現(xiàn) django 執(zhí)行 ansible playbook 任務(wù)時(shí)候,實(shí)時(shí)返回執(zhí)行信息到前端怎么搞的。
項(xiàng)目里現(xiàn)在使用 django 的 connection 連接 oracle 執(zhí)行 pl_sql 語句
是否可以在 django 通過什么方式獲取 dbms_output.put_line('...');在 oracle 控制臺上打印的信息?
前端表單
# ajax 進(jìn)行表單提交$('#jsStayForm').serialize()
提交后,獲取到的值為 virtual_cpu1=1&virtual_mem1=8&virtual_disk1=50&virtual_vlan1=1021&project1=111&nums1=1&virtual_cpu3=2&virtual_mem3=12&virtual_disk3=200virtual_vlan3=1021&project3=222&nums3=1&virtual_cpu2=3&virtual_mem2=18&virtual_disk2=150&virtual_vlan2=1021&project2=3333&nums2=1
那么我后臺要怎么拆分處理這一串內(nèi)容。 def post(self, request): virtual_post_data = request.POST for key,value in virtual_post_data.items(): print(key,value)
打印出 key,value 值如下 virtual_cpu1 1 virtual_mem1 2 virtual_disk1 50 virtual_vlan1 1021 project1 nums1 1 virtual_cpu3 3 virtual_mem3 2 virtual_disk3 50 virtual_vlan3 1021 project3 nums3 1 virtual_cpu2 2 virtual_mem2 2 virtual_disk2 50 virtual_vlan2 1021 project2 nums2 1
我最終需要的結(jié)果是,key 值最后數(shù)字一樣的分為一個(gè)組 [ {'virtual_cpu1':1,'virtual_mem1':2,'virtual_disk1':50}, {'virtual_cpu2':1,'virtual_mem2':2,'virtual_disk2':50}, {'virtual_cpu3':1,'virtual_mem3':2,'virtual_disk3':50} ]
現(xiàn)在問題是,取回的值都是一串字符的,不知如何進(jìn)行分組,各位大佬提點(diǎn)意見,無論前端或者后端進(jìn)行分組都行。
models.py class VirtualNode(models.Model): VIRTUAL_STATUS = ( (0, '已停止'), (1, '已啟動(dòng)'), (2, '正在創(chuàng)建'), (3, '創(chuàng)建失敗'), ) virtual_id = models.AutoField(verbose_name="虛擬機(jī) ID",primary_key=True) virtual_name = models.CharField(max_length=30,verbose_name="虛擬機(jī)名") virtual_ip = models.GenericIPAddressField(verbose_name="虛擬 IP") virtual_cpu = models.IntegerField(verbose_name="虛擬機(jī) cpu(核數(shù))") virtual_mem = models.IntegerField(verbose_name="虛擬機(jī)內(nèi)存(GB)") virtual_disk = models.IntegerField(verbose_name="虛擬機(jī)硬盤(GB)") virtual_vmnode = models.ForeignKey(VmNode, verbose_name="所屬宿主機(jī)") virtual_vlan = models.ForeignKey(VlanInfo,verbose_name="所屬 Vlan") project = models.CharField(max_length=30,verbose_name="所屬項(xiàng)目",null=True,blank=True) virtual_staus = models.IntegerField(verbose_name='運(yùn)行狀態(tài)',choices=VIRTUAL_STATUS,default=0) class Meta: verbose_name = "虛擬機(jī)節(jié)點(diǎn)" verbose_name_plural = verbose_name forms.py class VirtualNodeForm(forms.ModelForm): class Meta: model = VirtualNode fields = '__all__' vievws.py class VirtualNodeAddView(LoginRequireMixin, View): def get(self, request): pass def post(self, request): virtual_form = VirtualNodeForm(request.POST) if virtual_form.is_valid(): virtual_form.save() return JsonResponse({'status':'success'}) else: msg = virtual_form.errors.values() return JsonResponse({'status':'fail','msg':'虛擬機(jī)添加失?。簕}'.format(msg)})
前端的表單只會(huì)填 6 個(gè)字段
其中 virtual_name 、virtual_ip 會(huì)根據(jù)某些條件算出后自動(dòng)保存。
那么問題來了
在 views.py 里面怎么將 virtual_name virtual_ip ,回填到 virtual_form 里,否在在下面的校驗(yàn)無法通過。
按照網(wǎng)上的教程,配置好了 DjangoUeditor,其他功能都正常,可是點(diǎn)擊上傳圖片,彈出的窗口中顯示:
后端配置項(xiàng)沒有正常加載,上傳插件不能正常使用!
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
這里也配置了,請問一下有人知道是什么原因嗎?
還差哪一步?謝謝。。
如下截圖,存在這樣一張表 student model 有三個(gè)字段 name 學(xué)生姓名 score 分?jǐn)?shù) created_time 記錄創(chuàng)建時(shí)間 class StudentScore(models.Model): name = models.CharField('姓名', max_length=128) score = models.IntegerField(verbose_name='分?jǐn)?shù)') created_time = models.DateTimeField(auto_now_add=True)
每位學(xué)生可能有多條記錄, 我需要用每位學(xué)生最新的一條記錄,做一個(gè)排行榜, 用 django 的 orm 如何去查詢?
我想使用 django.contrib.comments 給我的網(wǎng)站添加一個(gè)評論功能,
按照網(wǎng)上的教程( https://mozillazg.com/2013/01/django-built-in-comments-framework.html )設(shè)置好了。
可是我測試了一下,點(diǎn)擊提交評論之后,它自動(dòng)跳轉(zhuǎn)到了: http://127.0.0.1:8000/comments/post/
這個(gè)地址,然后報(bào)錯(cuò):Exception Value: list index out of range
我現(xiàn)在的問題是: 1.比如,設(shè)置好 django.contrib.comments 之后,我還需要自己在 views 中寫 if request.method ==post 這樣的來處理這個(gè) post 請求嗎?還是 django.contrib.comments 已經(jīng)寫好了,我根本不用管了。
2.可是為什么我的不成功。我看他的報(bào)錯(cuò)信息那一行 city_details = Current.objects.filter(resortid = resortid) city_name = city_details[0].name
,在正常訪問時(shí),是沒有問題的,不知為什么發(fā)了評論之后就出問題。
請問有人知道原因么?謝謝。
今天配置 Django3.0 的錯(cuò)誤頁面,發(fā)現(xiàn)遠(yuǎn)沒有以前的版本那么方便,越改越不適應(yīng)了.
settings.py
DEBUG = False
ALLOWED_HOSTS = ['*']
urls.py
handler404 = views.page_not_found
handler500 = views.server_error
views.py
def page_not_found(request, exception): data = {} return render(request, 'blog/errors/page_404.html', data, status=404)
def server_error(request, exception): data = {} return render(request, 'blog/errors/page_500.html', data)
網(wǎng)上找了各種版本的配置,包括看了官方文檔就是配置不成功,不知道是哪里有問題 請各位有配置過 Django3.0 版本的朋友們,幫指點(diǎn)一下,謝謝了!在線等.
1 、封裝 ansible playbook api 后,直接腳本調(diào)用,可以執(zhí)行 yaml 任務(wù)。
https://i.imgur.com/cgCNruu.png
2 、在 django celery 進(jìn)行異步任務(wù)時(shí)候,無法執(zhí)行 yaml 任務(wù)
task 內(nèi)容
https://i.imgur.com/MBi3goA.png
在 views.py 進(jìn)行 task 調(diào)用
https://i.imgur.com/1lj6OUW.png
執(zhí)行結(jié)果,為空
https://i.imgur.com/7k27yRN.png
現(xiàn)在無法定位到哪里問題,望各位大老指點(diǎn)。
我們正需要開發(fā)一套管理系統(tǒng),請熟悉 Django 框架的公司、工作室或個(gè)人聯(lián)系。我司也有 python 開發(fā)人員協(xié)助配合
管理系統(tǒng)要求如下:
1 、采用 Django 框架 2 、多租戶,每個(gè)帳號只能看到自己錄入的信息 3 、通過 Http 對接 2 個(gè)第三方平臺(物聯(lián)網(wǎng)設(shè)備平臺 1 個(gè),數(shù)據(jù)平臺 1 個(gè))
聯(lián)系 WX: [email?protected] / [email?protected] (去掉 @和 /)
如題,前幾天看論壇討論帖都覺得 django 不錯(cuò),學(xué)前先測了測性能。。
配置:(平臺 ubuntu ) django-admin startproject helloworld # 編寫一個(gè) echo,訪問 127.0.0.1:8080 回復(fù)"hello world" gunicorn HelloWorld.wsgi -b 127.0.0.1:8080 -w 9
壓測: wrk -t16 -c500 -d10 http://127.0.0.1:8080
得到數(shù)據(jù):
單進(jìn)程 并發(fā) 794.46r/秒 ,平均延遲 140.74ms 九進(jìn)程 并發(fā) 7700r/秒,平均延遲 28ms
雖然之前就想到 django 不會(huì)很快,畢竟 py 寫服務(wù)性能也沒那么重要,但是這也慢的太太太太太夸張了吧。。本地 echo 居然只有 700qps 的性能,本地 echo 延遲 0.1 秒,這。。。。。。。。。
對比一下 py 框架現(xiàn)在異步框架性能單線程 express 也能挑戰(zhàn)一下的,就算 wsgi 跑的 flask,fork 的 rps 怎么也有兩萬,我用不到那么快,但是你也別慢的太夸張啊。。。。本地延遲這么高,干點(diǎn)啥畏首畏尾。。。。
是我哪里配置錯(cuò)了嗎?
如題,django 中貌似只有 bulk_update 和 bulk_create,有什么辦法可以實(shí)現(xiàn) bulk_update_or_create 嗎
現(xiàn)有一張成績表, 主鍵是用戶 id, 如何根據(jù)用戶 id 查詢該用戶在表中是否排在前 100 名以及上榜后的名次
另外,水平分表后,filter 要從多張表查詢,不僅增加了查詢次數(shù),還要對結(jié)果進(jìn)行合并。性能上是否可???
在“Designing Data-Intensive Applications - CHAPTER 5 Replication - Leaderless Replication - Detecting Concurrent Writes - Capturing the happens-before relationship”中,有這么一張圖:
之后它說: Note that the server can determine whether two operations are concurrent by looking at the version numbers—it does not need to interpret the value itself (so the value could be any data structure). The algorithm works as follows: The server maintains a version number for every key, increments the version number every time that key is written, and stores the new version number along with the value written. When a client reads a key, the server returns all values that have not been overwritten, as well as the latest version number. A client must read a key before writing. When a client writes a key, it must include the version number from the prior read, and it must merge together all values that it received in the prior read. (The response from a write request can be like a read, returning all current values, which allows us to chain several writes like in the shopping cart example.) When the server receives a write with a particular version number, it can overwrite all values with that version number or below (since it knows that they have been merged into the new value), but it must keep all values with a higher version number (because those values are concurrent with the incoming write).
我不太確定“我對覆蓋和保留的理解”是不是正確,我的理解如下所示:
目前我涉及到做點(diǎn)贊這塊,起初的設(shè)計(jì)是直接落庫,用戶的點(diǎn)贊和取消點(diǎn)贊直接對記錄進(jìn)行加減,這樣的方案似乎很簡單看起來也沒啥問題,但是一旦流量多了起來,數(shù)據(jù)庫肯定扛不住這么頻繁的讀寫。
我參考了一些網(wǎng)上教程,基本都是采用 redis 異步入庫,就是點(diǎn)贊和取消都交給 redis,redis 記錄了點(diǎn)贊人和被點(diǎn)贊人,同時(shí)在另外記錄點(diǎn)贊總數(shù),然后通過定時(shí)任務(wù)進(jìn)行異步落庫并刪除 redis 中的指定數(shù)據(jù)。
但是現(xiàn)在新的問題來了,當(dāng)我要查詢某個(gè)文章的點(diǎn)贊總數(shù)的時(shí)候,怎么保證數(shù)據(jù)的一致性呢,豈不是查詢的總數(shù)的時(shí)候需要 mysql+redis = 總數(shù)才能保證唯一性,因?yàn)?redis 入庫后記錄就被刪除了,防止內(nèi)存龐大,而且 redis 并不會(huì)做持久化,麻煩做過這方面的大牛給我指點(diǎn)指點(diǎn)
Redis 的高可用方案有兩種,哨兵和集群。
個(gè)人淺薄理解,哨兵模式就是創(chuàng)建一個(gè)備胎,備胎同步 master 數(shù)據(jù),在 master 出現(xiàn)異常的時(shí)候進(jìn)行切換。
而集群則是創(chuàng)建一個(gè) slave,slave 同步 master 數(shù)據(jù),可用于客戶端讀取,在 master 出現(xiàn)異常的時(shí)候進(jìn)行選舉切換為 master 。集群模式要求最少 3 個(gè) master 節(jié)點(diǎn),master 節(jié)點(diǎn)間分槽管理數(shù)據(jù)。
在正常情況下,哨兵就是個(gè)吃白飯的,沒有任何作用,而集群的 slave 則參與讀操作。
怎么看都是集群完勝啊,為啥還有人在堅(jiān)持維護(hù)哨兵模式呢(比如 helm 的 redis-ha)?
環(huán)境是 springboot2.0,連接池是 springboot 帶的 lettuce 配置使用的是默認(rèn)配置 現(xiàn)象就是 一段時(shí)間不是用 redis, 再去使用的時(shí)候就會(huì)報(bào) command timeout exception
下面是報(bào)錯(cuò)信息 Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:70) at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:41) at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44) at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42) at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:257) at org.springframework.data.redis.connection.lettuce.LettuceKeyCommands.convertLettuceAccessException(LettuceKeyCommands.java:650) at org.springframework.data.redis.connection.lettuce.LettuceKeyCommands.keys(LettuceKeyCommands.java:148) at org.springframework.data.redis.connection.DefaultedRedisConnection.keys(DefaultedRedisConnection.java:75) at org.springframework.data.redis.core.RedisTemplate.lambda$keys$10(RedisTemplate.java:840) at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224) at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184) at org.springframework.data.redis.core.RedisTemplate.keys(RedisTemplate.java:840)
早網(wǎng)上找了找沒找到什么有用的解決方案,特來請教
1.本地 windows 起了個(gè) 相同的代碼,相同數(shù)據(jù),就能全存進(jìn)去,部署的服務(wù)器上 就怎么都對不上數(shù)。 2.此 redis 還有其他項(xiàng)目在用,但代碼層面,可以排除影響。 3.每次都是 4520 4.配置里沒設(shè)最大值限制 5.以前沒出現(xiàn)過類似情況,這套代碼部署過好多個(gè)服務(wù)器 6.KEY 絕對沒有重復(fù),這個(gè)反復(fù)驗(yàn)證過了 7.沒看到哪報(bào)錯(cuò)了 …… w(?Д?)w~~~~~ w(?Д?)w~~~ w(?Д?)w
在 Distributed locks with Redis – Redis 中,首先它描述了如何正確地使用單實(shí)例實(shí)現(xiàn)分布式鎖,然后它介紹了分布式版本的算法。但是對于分布式版本,我有許多疑問。
首先,那篇文章說 In the distributed version of the algorithm we assume we have N Redis masters. Those nodes are totally independent, so we don’t use replication or any other implicit coordination system. We already described how to acquire and release the lock safely in a single instance. We take for granted that the algorithm will use this method to acquire and release the lock in a single instance. In our examples we set N=5, which is a reasonable value, so we need to run 5 Redis masters on different computers or virtual machines in order to ensure that they’ll fail in a mostly independent way. In order to acquire the lock, the client performs the following operations: It gets the current time in milliseconds. It tries to acquire the lock in all the N instances sequentially, using the same key name and random value in all the instances. During step 2, when setting the lock in each instance, the client uses a timeout which is small compared to the total lock auto-release time in order to acquire it. For example if the auto-release time is 10 seconds, the timeout could be in the ~ 5-50 milliseconds range. This prevents the client from remaining blocked for a long time trying to talk with a Redis node which is down: if an instance is not available, we should try to talk with the next instance ASAP. The client computes how much time elapsed in order to acquire the lock, by subtracting from the current time the timestamp obtained in step 1. If and only if the client was able to acquire the lock in the majority of the instances (at least 3), and the total time elapsed to acquire the lock is less than lock validity time, the lock is considered to be acquired. If the lock was acquired, its validity time is considered to be the initial validity time minus the time elapsed, as computed in step 3. If the client failed to acquire the lock for some reason (either it was not able to lock N/2+1 instances or the validity time is negative), it will try to unlock all the instances (even the instances it believed it was not able to lock).
我的疑問 為什么要順序地嘗試獲取所有實(shí)例里的鎖呢?同時(shí)嘗試獲取會(huì)存在什么問題呢? Redlock 算法所說的 auto-release time 是類似于 Distributed locks with Redis – Redis - Correct implementation with a single instance 中所說的 SET resource_name my_random_value NX PX {ttl} 中的 ttl 嗎?也就是我下面所說的 TTL,是嗎? 在第二步時(shí),會(huì)嘗試在所有實(shí)例中獲取鎖,它所做的行為跟單實(shí)例所做的行為是一樣的,也就是 SET resource_name my_random_value NX PX {ttl} ,那么 ttl 是怎么計(jì)算出來的呢?我認(rèn)為不同實(shí)例的 ttl 是不同的,因?yàn)閲L試獲取在不同的實(shí)例里的鎖的時(shí)間是不一樣的。因?yàn)橐_?!叭绻袑?shí)例的同一個(gè) key 都在同一時(shí)間被刪除”,所以我覺得每個(gè)實(shí)例里所設(shè)置的 ttl 是“ TTL - (在某個(gè)實(shí)例嘗試獲取鎖的時(shí)間 - 第一步獲取到的時(shí)間) ”,對嗎?(這里的 TTL 表示的是邏輯上的 TTL,并不是真實(shí)設(shè)置在某個(gè)實(shí)例里的 ttl,也就是所有實(shí)例里的同一個(gè) key 都會(huì)在“第一步獲取到的時(shí)間 + TTL”這個(gè)時(shí)間被刪除)
其實(shí)我心里大概是有一個(gè)答案的,就是怕斷電丟 5 分鐘左右的數(shù)據(jù)?
如果不考慮斷電的情況呢,因?yàn)榘⒗镌乞v訊云我用了好多年都沒遇到過斷電,而且就丟失 5 分鐘,概率上還沒有中勒索病毒大。
其他的我暫時(shí)也想不到什么壞處,頂多是邏輯要自己寫,大表拆分起來要?jiǎng)觿?dòng)腦。
好處不用說了,速度起飛,內(nèi)存占用低。
所以還是想請教一下各位大佬,到底有沒有可行性
我記得有個(gè)命令可以顯示使用的是哪個(gè)配置文件。 現(xiàn)在記不得了
、、、 [email?protected] :/home/ubuntu/redis-4.0.11# ps -ef | grep -i redis root 23189 1 0 12:05 ? 00:00:00 redis-server *:6379 root 23249 22790 0 12:05 pts/5 00:00:00 grep --color=auto -i redis
[email?protected] :/home/ubuntu/redis-4.0.11# kill 23189 [email?protected] :/home/ubuntu/redis-4.0.11# cd src
[email?protected] :/home/ubuntu/redis-4.0.11/src# redis-server ../redis.conf 23297:C 15 Jun 12:05:52.164 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 23297:C 15 Jun 12:05:52.164 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=23297, just started 23297:C 15 Jun 12:05:52.164 # Configuration loaded [email?protected] :/home/ubuntu/redis-4.0.11/src# 、、、
自從最新的自行編譯版不能使用 SSH 通道以后,一直在使用去年版的,最近看官網(wǎng),發(fā)現(xiàn)上架了 Win10 商店了
看了一下中國區(qū)的價(jià)格還挺不錯(cuò)的,只要 50 塊錢,對于我這種有三臺電腦的來說也很方便,不需要自己去更新了,也不會(huì)有自行編譯版本的各種 GUI 問題。
看介紹反正沒說是不是訂閱制,就當(dāng)他永久的。
PS: 發(fā)現(xiàn)這玩意竟然還有 iPadOS 版本,要占領(lǐng)地球?
用戶姓名 出生日期 性別什么的 k v 存 redis 。
想一次性全部取出來不行嗎 還是 scan ?
我現(xiàn)在需要根據(jù)充值表來統(tǒng)計(jì)每個(gè)公司、部門、小組(級別可能是有 N 級)以及個(gè)人(個(gè)人還分不同崗位)的今日、本月、上月以及累計(jì)充值金額的排行榜功能(排行榜一小時(shí)更新一次)。目前打算用 redis 的 zSet 來處理,但是感覺工程量巨大(可能是因?yàn)槲宜悸峰e(cuò)了),所以請教下如何設(shè)計(jì)比較好?
3 個(gè)小時(shí)前 Antirez 在博客上發(fā)文《 Redis 6.0.0 GA is out!》,從 RC1 版本到今天,算下來也有 130 多天了,除了在 RC1 上已經(jīng)知道的新功能(沒有了解的同學(xué)可以看一下我的這篇譯文: https://www.v2ex.com/t/630926#reply15 ),這段時(shí)間內(nèi) Redis 還做了很多優(yōu)化、更新和功能的重做。
先提綱回顧一下 Redis 6 RC1 時(shí)相對于 Redis 5 的變化: 眾多新模塊( modules ) API 更好的過期循環(huán)( expire cycle ) SSL ACLs 權(quán)限控制 RESP3 協(xié)議 客戶端緩存( Client side caching ) 多線程 IO ( Threaded I/O ) 無盤復(fù)制副本( Diskless replication on replicas ) Redis-benchmark 的集群支持和 Redis-cli 優(yōu)化 重寫 Systemd 支持( Systemd support rewrite ) Redis 集群代理與 Redis 6 一同發(fā)布(但在不同的 repo ) Disque 模塊與 Redis 6 一同發(fā)布
那么下面才是今天的主角,RC1 至 GA 期間的改動(dòng): 客戶端緩存的重做,用了新的實(shí)現(xiàn)( broadcasting mode ) 用于主從復(fù)制的 RDB 文件會(huì)在完成使命后刪除 新增 ACL LOG 命令,這是 Antirez 在 twitch 上直播開發(fā)的功能,直播 coding 過程挺有意思的,言歸正傳,這個(gè)命令提供兩個(gè)功能:查看最近 ACL 不通過的命令和用戶 & 清理 ACL 不通過的日志;當(dāng)然還有自動(dòng)生成密碼命令( ACL GENPASS )的一些內(nèi)容,具體可以看博文原文。 優(yōu)化 PSYNC2 帶超時(shí)選項(xiàng)的命令優(yōu)化 RDB 文件加載優(yōu)化,20-30%的提升 上個(gè)月新加的命令( STARLGO ),結(jié)合 Redis 和 LCS (最長公共字符串)的算法來實(shí)現(xiàn)一些功能
以下是博文原文 1. Client side caching was redesigned in certain aspects, especially the caching slot approach was discarded in favor of just using key names. After analyzing the alternatives, with the help of other Redis core team members, in the end this approach looks better. Other than that, finally the feature was completed with the things I had in the backlog for the feature, especially the “broadcasting mode”, that I believe will be one of the most popular usage modes of the feature. When broadcasting is used, the server no longer try to remember what keys each client requested. Instead clients subscribe to key prefixes: they’ll get notifications every time a key matching the prefix is modified. This means more messages (but only for the selected prefixes), but no memory effort in the server side. Moreover the opt-in / opt-out mode is now supported, so it is possible for clients not using the broadcasting mode, to exactly tell the server about what the client will cache, to reduce the number of invalidation messages. Basically the feature is now much better both when a low-memory mode is needed, and when a very selective (low-bandwidth) mode is needed. 2. This was an old request by many users. Now Redis supports a mode where RDB files used for replication are immediately deleted if no longer useful. In certain environments it is a good idea to never have the data around on disk, but just in memory. 3. ACLs are better in a few regards. First, there is a new ACL LOG command that allows to see all the clients that are violating the ACLs, accessing commands they should not, accessing keys they should not, or with failed authentication attempts. The log is actually in memory, so every external agent can call “ACL LOG” to see what’s going on. This is very useful in order to debug ACL problems. But my preferred feature is the reimplementation of ACL GENPASS. Now it uses SHA256 based HMAC, and accepts an optional argument to tell the server how many bits of unguessable pseudo random string you want to generate. Redis seeds an internal key at startup from /dev/urandom, and later uses the HMAC in counter mode in order to generate the other random numbers: this way you can abuse the API, and call it every time you want, since it will be very fast. Want to generate an unguessable session ID for your application? Just call ACL GENPASS. And so forth. 4. PSYNC2, the replication protocol, is now improved. Redis will be able to partially resynchronize more often, since now is able to trim the final PINGs in the protocol, to make more likely that replicas and masters can find a common offset. 5. Redis commands with timeouts are now much better: not only BLPOP and other commands that used to accept seconds, now accept decimal numbers, but the actual resolution was improved in order to never be worse than the current “HZ” value, regardless of the number of clients connected. 6. RDB files are now faster to load. You can expect a 20/30% improvement, depending on the file actual composition (larger or smaller values). INFO is also faster now when there are many clients connected, this was a long time problem that now is finally gone. 7. We have a new command, STRALGO, that implements complex string algorithms. For now the only one implemented is LCS (longest common subsequence), an important algorithm used, among the other things, in order to compare the RNA of the coronaviruses (and in general the DNA and RNA of other organisms). What is happening is too big, somewhat a trace inside Redis needed to remain.
需求:
這是昨天面試中遇到的一個(gè)問題,當(dāng)用戶 x 秒內(nèi)請求 y 次,禁止用戶訪問
先寫一些我自己想的方案,下面的 windowStart 為 x 秒之前的 timestamp, current 為現(xiàn)在的 timestamp, threshold 為請求次數(shù)限制。下列方法都需要設(shè)置和更新 key 過期時(shí)間,以免造成 key 泄漏。
方案 1:
用 Redis 的 List 數(shù)據(jù)結(jié)構(gòu)記錄用戶訪問的時(shí)間
當(dāng)用戶訪問時(shí) rpush 當(dāng)前時(shí)間戳并刪掉左側(cè) x 秒之前的時(shí)間戳,此時(shí)該列表的長度為 x 秒請求次數(shù),注意此方法的 timestamp 需要用 Redis 的 Lua 腳本否則可能因?yàn)楦鳈C(jī)器時(shí)間不同出問題(例如某臺機(jī)器時(shí)間為未來,則 ltrim 不到該條數(shù)據(jù)后面的正常時(shí)間戳)
偽代碼: redis.rpush(key, current); redis.expire(key, current + y); counter = 0; while (redis.get(key, 0) < windowStart) { counter++; } redis.ltrim(0, counter); if (redis.llen(key) > y) { doBanUser(); }
方案 1 的問題:
只需要最多存 y 條數(shù)據(jù),但是這里用到了 List,Redis 中的 List 為雙向鏈表,每個(gè)節(jié)點(diǎn)包含兩個(gè)指針,在 64 位機(jī)器上占用 128bit,而實(shí)際有用的時(shí)間戳只要 64bit 。迭代鏈表時(shí)會(huì)更慢一些。
方案 2:
使用數(shù)組 ringbuffer 代替方案一的鏈表。
方案 2 的問題:
需要自己開發(fā) Redis module,開發(fā)和運(yùn)維成本較高。另外方案 1 和方案 2 中均存不方便重試和測試的問題。例如其他業(yè)務(wù)調(diào)自己服務(wù)但是自己服務(wù)超時(shí),此時(shí)業(yè)務(wù)方重試,這種情況不應(yīng)該算用戶訪問了兩次。
方案 3:
使用 Redis 的 ZSet 數(shù)據(jù)結(jié)構(gòu)
以用戶請求的唯一 requestId 為 member,當(dāng)前時(shí)間為 score,如果 requestId 已存在( logn 復(fù)雜度),不進(jìn)行任何操作,如果不存在,則 ZADD,然后使用 ZRANGEBYSCORE 查看該時(shí)間段內(nèi)請求數(shù)量。該方案同時(shí)需要使用 ZREMRANGEBYSCORE 來刪除過老的元素,我認(rèn)為可以每次或 N 次請求的時(shí)候刪除,面試官說有更好的刪除時(shí)機(jī),但是我也沒有問,這個(gè)問題就這么過去了。
想問問 V 友該方法應(yīng)該如何刪除,或者有沒有更好的方法來用 Redis 限制用戶行為頻率?
開了 VPN, 已確認(rèn) 配置沒問題,打的包在服務(wù)器上運(yùn)行也可以,就是本地 DEBUG 不行。是不是 idea 有特殊端口 vpn 沒開?
問題點(diǎn):Redis 啟動(dòng)出現(xiàn)兩個(gè) Warning 。 一個(gè) TCP backlog setting of 511 somaxconn value of 128; 一個(gè)是要求 vm.overcommit_memory=1;
修復(fù)嘗試:我按照網(wǎng)上的方法,在 sysctl.conf 文件中新增了 net.core.somaxconn 和 vm.overcommit_memory, 但只有 vm.overcommit_memory 起效果了,而且一旦重啟電腦又會(huì)重現(xiàn)錯(cuò)誤,并未像網(wǎng)上那樣永久解決。 運(yùn)行 sysctl -a 命令顯示 net.core.somaxconn 的值一直是 128 。
錯(cuò)誤起因:NET 項(xiàng)目,最近加了 SignalR,前端小程序用了 Websocket 與后端建立實(shí)時(shí)通信。
目的:reids 啟動(dòng)不再出現(xiàn)這兩個(gè)錯(cuò)誤。
PS:中午再回復(fù)
《 redis 》設(shè)計(jì)與實(shí)現(xiàn) 218 頁,15.7.3”檢測命令丟失“
”但這條命令卻因?yàn)榫W(wǎng)絡(luò)故障而在傳播的過程中丟失,那么主從服務(wù)器之間的復(fù)制偏移量就會(huì)出現(xiàn)不一致“
主從之間是 tcp 連接,已經(jīng)保證了可靠傳輸,為什么還要考慮”命令丟失“?