如何優(yōu)雅地運用位運算實現(xiàn)產(chǎn)品需求到推?

原文地址:梁桂釗的博客

博客地址:http://blog.720ui.com

歡迎關(guān)注公眾號:「服務(wù)端思維」。一群同頻者惕澎,一起成長莉测,一起精進,打破認知的局限性唧喉。

如何優(yōu)雅地運用位運算實現(xiàn)產(chǎn)品需求捣卤?

在開始正文之前,我們先來說一下 Linux 的系統(tǒng)權(quán)限設(shè)計八孝。在 Linux 系統(tǒng)中董朝,為了保證文件的安全,對文件所有者干跛、同組用戶子姜、其他用戶的訪問權(quán)限進行了分別管理。其中楼入,文件所有者哥捕,即建立文件或目錄的用戶牧抽。同組用戶,是所屬組群中的所有用戶遥赚。其他用戶扬舒,指的是既不是文件所有者,也不是同組用戶的其他用戶凫佛。每個文件和目錄都具有讀取權(quán)限讲坎、寫入權(quán)限和執(zhí)行權(quán)限,這三個權(quán)限之間相互獨立愧薛。

image.png

在 Linux 系統(tǒng)中晨炕,每個文件的訪問權(quán)限可以用 9 個字母表示,每 3 個字母表示一類用戶權(quán)限毫炉,分別代表文件創(chuàng)建者府瞄、同組用戶、其他用戶碘箍。其中,r 表示讀取權(quán)限鲸郊,w 表示寫入權(quán)限丰榴,x 表示執(zhí)行權(quán)限。通過功能模式修改文件權(quán)限秆撮,有三個部分組成四濒,包括對象、操作和權(quán)限职辨。

image.png

假設(shè)需要增加同組用戶寫入權(quán)限盗蟆,下面來看一個例子。

chmod g+w /root/install.log

此外舒裤,每一類用戶的訪問也可以通過數(shù)字的方式進行表示喳资。

image.png

那么,通過數(shù)字模式就可以對常見的 Linux 文件權(quán)限操作進行歸納腾供。

image.png

假設(shè)需要設(shè)置創(chuàng)建者可讀可寫可執(zhí)行仆邓、同組用戶可讀、其他用戶可讀伴鳖,我們可以這樣寫:

chmod 755 /root/install.log

事實上节值,Linux 的文件訪問權(quán)限就是非常經(jīng)典的位運算使用場景。無獨有偶榜聂,我們再來看下 Java 中的 java.lang.reflect.Modifier 搞疗。其中, Modifier 類采用 16 進制定義了靜態(tài)常量须肆。

public static final int PUBLIC           = 0x00000001;
public static final int PRIVATE          = 0x00000002;
public static final int PROTECTED        = 0x00000004;
public static final int STATIC           = 0x00000008;
public static final int FINAL            = 0x00000010;
public static final int SYNCHRONIZED     = 0x00000020;
public static final int VOLATILE         = 0x00000040;
public static final int TRANSIENT        = 0x00000080;
public static final int NATIVE           = 0x00000100;
public static final int INTERFACE        = 0x00000200;
public static final int ABSTRACT         = 0x00000400;
public static final int STRICT           = 0x00000800;
...

緊接著匿乃,Modifier 類提供了很多靜態(tài)方法桩皿,例如 isPublic() 方法的返回值 & PUBLIC 對應(yīng)的 16 進制值,如果非 0扳埂,則說明含有 public 修飾符业簿。

public static boolean isPublic(int mod) {
    return (mod & PUBLIC) != 0;
}

這里有一個重要的知識點,采用 & 運算阳懂,兩位同時為 1梅尤,結(jié)果才為 1,否則為 0岩调。即 0&0=0; 0&1=0; 1&0=0; 1&1=1巷燥。例如:3&1 即 0000 0011 & 0000 0001 = 00000001,值為 1号枕。

     0000 0011
&    0000 0001 
=    0000 0001  

與此同時缰揪,Modifier 類還采用 | 運算,確保參加運算的兩個對象只要有一個為 1葱淳,其值為 1钝腺。即 0|0=0; 0|1=1赞厕; 1|0=1艳狐;1|1=1。例如 Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICT 的結(jié)果是 3103皿桑,即 110000011111毫目。

private static final int CLASS_MODIFIERS =
        Modifier.PUBLIC         | Modifier.PROTECTED    | Modifier.PRIVATE |
        Modifier.ABSTRACT       | Modifier.STATIC       | Modifier.FINAL   |
        Modifier.STRICT;

     0000 0000 0000 0001
|   0000 0000 0000 0010 
|   0000 0000 0000 0100 
|   0000 0000 0000 1000 
|   0000 0000 0001 0000 
|   0000 0100 0000 0000
|   0000 1000 0000 0000
=    0000 1100 0001 1111

書歸正傳,我們站在前輩們的肩上诲侮,通過位運算設(shè)計優(yōu)雅的多選標識镀虐,例如通過位運算實現(xiàn)權(quán)限控制或多狀態(tài)管理,它的好處在于易擴展沟绪,避免數(shù)據(jù)庫設(shè)計過程中字段膨脹刮便,減少磁盤存儲空間。

假設(shè)近零,我們現(xiàn)在有一個有一個業(yè)務(wù)需求:在任務(wù)中添加一個通知方式诺核,可選項包括 IM 消息、系統(tǒng)提醒久信、郵箱窖杀、短信。選擇 IM 消息后裙士,支持 IM 即時發(fā)送入客;選擇系統(tǒng)提醒后,支持站內(nèi)信推送;選擇選擇郵箱后桌硫,該任務(wù)后續(xù)相關(guān)提醒內(nèi)容夭咬,可通過發(fā)送郵件至相關(guān)人郵箱中進行通知;選擇短信后铆隘,該任務(wù)后續(xù)相關(guān)提醒內(nèi)容卓舵,可通過發(fā)送短信至相關(guān)人進行通知。

image.png

我們在設(shè)計數(shù)據(jù)庫庫表時膀钠,通常情況下掏湾,將多個標識字段合并成一個字段,并把這個字段改成字符串型方式保存肿嘲,例如融击,存在 1 時表示支持 IM,2 時表示支持系統(tǒng)消息雳窟,3 表示支持郵箱尊浪,4 表示支持短信。此時封救,如果同時都滿足拇涤,它的存儲形式就是以逗號分隔的字符串:“1,2,3,4”。這樣設(shè)計的好處在于誉结,不僅消除相同字段的冗余工育,而且當增加新的渠道類別時,不需增加新的字段搓彻。

IM(1, "IM消息"),
SYSTEM(2, "系統(tǒng)提醒"),
MAIL(3, "郵箱"),
SMS(4, "短信");

但在數(shù)據(jù)查詢時,我們需要對字符串進行分隔嘱朽。并且字符串類型的字段在查詢效率和存儲空間上不如整型字段旭贬。因此,我們可以用“位”來解決這個問題搪泳。我們采取不同的位來分別表示不同類別的標識字段稀轨。

image.png

因此,當某個任務(wù)支持 IM 時岸军,則保存 1(0000 0001)奋刽;支持系統(tǒng)消息時,則保存 2(0000 0010)艰赞,支持郵箱時佣谐,則保存 4(0000 0100);支持短信時方妖,則保存 8(0000 1000)狭魂。四種都支持,則保存 15 (0000 11111)。

說明
00000001 1 支持IM
00000010 2 支持系統(tǒng)消息
00000011 3 支持IM雌澄、系統(tǒng)消息
00000100 4 支持郵箱
00000101 5 支持郵箱斋泄、IM
00000110 6 支持郵箱、系統(tǒng)消息
00000111 7 支持郵箱镐牺、IM炫掐、系統(tǒng)消息
00001000 8 支持短信
...
00001111 15 支持郵箱、IM睬涧、系統(tǒng)消息募胃、短信

緊接著,我們通過封裝常用方法來實現(xiàn)增刪改宙地。

/**
 * 判斷
 * @param mod 用戶當前值
 * @param value  需要判斷值
 * @return 是否存在
 */
public static boolean hasMark(long mod, long value) {
    return (mod & value) == value;
}

/**
 * 增加
 * @param mod 已有值
 * @param value  需要添加值
 * @return 新的狀態(tài)值
 */
public static long addMark(long mod, long value) {
    if (hasMark(mod, value)) {
        return mod;
    }
    return (mod | value);
}

/**
 * 刪除
 * @param mod 已有值
 * @param value  需要刪除值
 * @return 新值
 */
public static long removeMark(long mod, long value) {
    if (!hasMark(mod, value)) {
        return mod;
    }
    return mod ^ value;
}

總結(jié)一下摔认,我們在數(shù)據(jù)庫設(shè)計時,將多個標識字段合并成一個字段宅粥,并把這個字段改成字符串型方式保存参袱,不僅消除相同字段的冗余,而且當增加新的渠道類別時秽梅,不需增加新的字段抹蚀,但是字符串類型的字段在查詢效率和存儲空間上不如整型字段。因此企垦,我們可以參考用“位”來解決這個問題环壤。我們采取不同的位來分別表示不同類別的標識字段。

寫在末尾

【服務(wù)端思維】:我們一起聊聊服務(wù)端核心技術(shù)钞诡,探討一線互聯(lián)網(wǎng)的項目架構(gòu)與實戰(zhàn)經(jīng)驗郑现。讓所有孤軍奮戰(zhàn)的研發(fā)人員都找到屬于自己的圈子,一起交流荧降、探討接箫。在這里,我們可以認知升級朵诫,連接頂級的技術(shù)大牛辛友,連接優(yōu)秀的思維方式,連接解決問題的最短路徑剪返,連接一切優(yōu)秀的方法废累,打破認知的局限。

更多精彩文章脱盲,盡在「服務(wù)端思維」邑滨!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市钱反,隨后出現(xiàn)的幾起案子驼修,更是在濱河造成了極大的恐慌殿遂,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乙各,死亡現(xiàn)場離奇詭異墨礁,居然都是意外死亡,警方通過查閱死者的電腦和手機耳峦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門恩静,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蹲坷,你說我怎么就攤上這事驶乾。” “怎么了循签?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵级乐,是天一觀的道長。 經(jīng)常有香客問我县匠,道長风科,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任乞旦,我火速辦了婚禮贼穆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘兰粉。我一直安慰自己故痊,他們只是感情好,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布玖姑。 她就那樣靜靜地躺著愕秫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪焰络。 梳的紋絲不亂的頭發(fā)上豫领,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機與錄音舔琅,去河邊找鬼。 笑死洲劣,一個胖子當著我的面吹牛备蚓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播囱稽,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼郊尝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了战惊?” 一聲冷哼從身側(cè)響起流昏,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后况凉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谚鄙,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年刁绒,在試婚紗的時候發(fā)現(xiàn)自己被綠了闷营。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡知市,死狀恐怖傻盟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嫂丙,我是刑警寧澤娘赴,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站跟啤,受9級特大地震影響诽表,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜腥光,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一关顷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧武福,春花似錦议双、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至伍纫,卻和暖如春宗雇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背莹规。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工赔蒲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人良漱。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓舞虱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親母市。 傳聞我的和親對象是個殘疾皇子矾兜,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355