Python 訂單號生成方案(高并發(fā) 根據(jù)java源碼重寫)

# -*- coding: utf-8 -*-
# 時間工具
import time
import numpy as nu
import util


class Date(object):
    """
    日期對象
    """

    __seconds = 0

    def __init__(self, seconds=None):
        """
        初始化時間對象
        :param seconds: 時間戳秒
        """
        self.setTime(seconds)

    def setTime(self, seconds=None):
        """
        設置時間戳
        :param seconds:
        :return:
        """
        if seconds is None:
            seconds = self.now()
        self.__seconds = seconds

    def timeFormat(self, format='%Y-%m-%d %H:%M:%S', seconds=None):
        """
        時間格式化
        :param format: 格式化方案
        :param seconds: 秒 如果不填則默認為當前對象秒
        :return:
        """
        seconds = self.__check_seconds(seconds)
        return time.strftime(format, time.localtime(seconds))

    def getSecond(self, seconds=None):
        """
        獲取秒鐘
        :param seconds:
        :return:
        """
        seconds = self.__check_seconds(seconds)
        return time.strftime('%S', time.localtime(seconds))

    def getSeparate(self, seconds=None):
        """
        獲取分鐘
        :param seconds:
        :return:
        """
        seconds = self.__check_seconds(seconds)
        return time.strftime('%M', time.localtime(seconds))

    def getHour(self, seconds=None):
        """
        獲取小時
        :param seconds:
        :return:
        """
        seconds = self.__check_seconds(seconds)
        return time.strftime('%H', time.localtime(seconds))

    def getDay(self, seconds=None):
        """
        獲取月中的日
        :param seconds:
        :return:
        """
        seconds = self.__check_seconds(seconds)
        return time.strftime('%d', time.localtime(seconds))

    def getMonth(self, seconds=None):
        """
        獲取月
        :param seconds:
        :return:
        """
        seconds = self.__check_seconds(seconds)
        return time.strftime('%m', time.localtime(seconds))

    def getYear(self, seconds=None):
        """
        獲取年
        :param seconds:
        :return:
        """
        seconds = self.__check_seconds(seconds)
        return time.strftime('%Y', time.localtime(seconds))

    def __check_seconds(self, seconds=None):
        """
        校驗時間戳-秒 參數(shù)
        :param seconds:
        :return:
        """
        if seconds is None:
            if self.__seconds is None:
                seconds = self.now()
            else:
                seconds = self.__seconds
        return seconds

    @staticmethod
    def now(mode='s'):
        """
        獲取時間戳方案
        :param mode: s 秒 ms 毫秒 ns 納秒
        :return:
        """
        time_mode = nu.array(util.TimeMode)
        if not (time_mode == mode).any():
            mode = util.TimeMode[0]
        ns = str(time.time_ns())
        if mode == util.TimeMode[0]:
            return int(ns[:len(ns) - 9])
        if mode == util.TimeMode[1]:
            return int(ns[:len(ns) - 6])
        if mode == util.TimeMode[2]:
            return int(ns)
# -*- coding: utf-8 -*-
# 異常對象組


class AuthException(Exception):
    """
    自定義異常對象 - 帶消息參數(shù)方案
    """
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return self.msg
# -*- coding: utf-8 -*-
# 隨機工具
from exceptions import AuthException
from util.time_util import Date


class OrderNumber(object):
    """
    訂單號生成對象
    """
    # 開始時間戳
    __twepoch = 1420041600000
    # 機器id所占的位數(shù)
    __worker_id_bits = 5
    # 數(shù)據(jù)標識id所占的位數(shù)
    __datacenter_id_bits = 5
    # 支持的最大機器id
    __max_worker_id = -1 ^ (-1 << __worker_id_bits)
    # 支持的最大標識id
    __max_datacenter_id = -1 ^ (-1 << __datacenter_id_bits)
    # 序列在id中占的位數(shù)
    __sequence_bits = 12
    # 機器id向左偏移位
    __worker_id_shift = __sequence_bits
    # 數(shù)據(jù)標識id向左偏移數(shù)
    __datacenter_id_shift = __sequence_bits + __worker_id_shift
    # 時間戳向左偏移數(shù)
    __timestamp_left_shift = __sequence_bits + __worker_id_bits + __datacenter_id_bits
    # 生成序列的掩碼
    __sequence_mask = -1 ^ (-1 << __sequence_bits)
    # 當前工作的機器id
    __worker_id = 0
    # 毫秒內(nèi)序列
    __datacenter_id = 0
    # 毫秒內(nèi)序列
    __sequence = 0
    # 上一次生成id時的時間戳
    __last_timestamp = -1

    def __init__(self, worker_id=0, datacenter_id=0):
        """
        構造函數(shù)
        :param worker_id: 工作id
        :param datacenter_id: 數(shù)據(jù)中心id
        """
        if worker_id > self.__max_worker_id or worker_id < 0:
            raise AuthException("worker Id can't be greater than {} or less than 0".format(self.__max_worker_id))
        if datacenter_id > self.__max_datacenter_id or datacenter_id < 0:
            raise AuthException(
                "datacenter Id can't be greater than %d or less than 0".format(self.__max_datacenter_id))
        self.__worker_id = worker_id
        self.__datacenter_id = datacenter_id

    @staticmethod
    def __time_gen():
        """
        獲取當前時間(毫秒級)
        :return:
        """
        return Date().now('ms')

    def __time_next_millis(self, last_timestamp: int):
        """
        阻塞到下一毫秒級,直到獲取到新的時間戳
        :param last_timestamp: 上一次生成id的時間戳
        :return:
        """
        timestamp = self.__time_gen()
        while timestamp <= last_timestamp:
            timestamp = self.__time_gen()
        return timestamp

    def next_id(self):
        """
        獲取下一個id
        :return:
        """
        timestamp = self.__time_gen()
        if timestamp < self.__last_timestamp:
            raise AuthException("Clock moved backwards.  Refusing to generate id for {} milliseconds".format(
                self.__last_timestamp - timestamp))
        if self.__last_timestamp == timestamp:
            self.__sequence = (self.__sequence + 1) & self.__sequence_mask
            if self.__sequence == 0:
                timestamp = self.__time_next_millis(self.__last_timestamp)
        else:
            self.__sequence = 0
        self.__last_timestamp = timestamp
        return ((timestamp - self.__twepoch) << self.__timestamp_left_shift) | (
                self.__datacenter_id << self.__datacenter_id_shift) | (
                       self.__worker_id << self.__worker_id_shift) | self.__sequence

# demo
# import util.random_util as ur
# import threading
#
#
# orders = []
# threads = []
#
#
# def for_run(worker_id=0, datacenter_id=0, thread_num=1):
#     order = ur.OrderNumber(worker_id, datacenter_id)
#     for i in range(0, 2000):
#         order_number = str(order.next_id())
#         orders.append(order_number)
#         print('進程{}: 生成的訂單號為:'.format(str(thread_num)) + order_number)
#
#
# if __name__ == '__main__':
#     for j in range(0, 30):
#         t = threading.Thread(target=for_run, args=(j, 0, j))
#         threads.append(t)
#     for t in threads:
#         t.setDaemon(True)
#         t.start()
#     for t in threads:
#         t.join()
#     print(len(orders))
#     orders = list(set(orders))
#     print(len(orders))

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末疏遏,一起剝皮案震驚了整個濱河市哩掺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖袖瞻,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萝喘,死亡現(xiàn)場離奇詭異鳖孤,居然都是意外死亡岗憋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門欠母,熙熙樓的掌柜王于貴愁眉苦臉地迎上來欢策,“玉大人,你說我怎么就攤上這事赏淌〔瓤埽” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵六水,是天一觀的道長俺孙。 經(jīng)常有香客問我,道長缩擂,這世上最難降的妖魔是什么鼠冕? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮胯盯,結果婚禮上懈费,老公的妹妹穿的比我還像新娘。我一直安慰自己博脑,他們只是感情好憎乙,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布票罐。 她就那樣靜靜地躺著,像睡著了一般泞边。 火紅的嫁衣襯著肌膚如雪该押。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天阵谚,我揣著相機與錄音蚕礼,去河邊找鬼。 笑死梢什,一個胖子當著我的面吹牛奠蹬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嗡午,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼囤躁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了荔睹?” 一聲冷哼從身側響起狸演,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎僻他,沒想到半個月后宵距,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡中姜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年消玄,在試婚紗的時候發(fā)現(xiàn)自己被綠了乡摹。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徘键。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡厕吉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出携龟,到底是詐尸還是另有隱情,我是刑警寧澤勘高,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布峡蟋,位于F島的核電站,受9級特大地震影響华望,放射性物質發(fā)生泄漏蕊蝗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一赖舟、第九天 我趴在偏房一處隱蔽的房頂上張望蓬戚。 院中可真熱鬧,春花似錦宾抓、人聲如沸子漩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幢泼。三九已至紧显,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缕棵,已是汗流浹背孵班。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留招驴,地道東北人重父。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像忽匈,于是被迫代替她去往敵國和親房午。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容