diff --git a/C#.NET/source/YitIdGen.WinFormApp/Program.cs b/C#.NET/source/YitIdGen.WinFormApp/Program.cs new file mode 100644 index 0000000000000000000000000000000000000000..21301c53112e1ff8d5c0b4d48e796c0fe8fa9ff5 --- /dev/null +++ b/C#.NET/source/YitIdGen.WinFormApp/Program.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WInFormApp +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new StartForm()); + } + } +} diff --git a/C#.NET/source/YitIdGen.WinFormApp/StartForm.Designer.cs b/C#.NET/source/YitIdGen.WinFormApp/StartForm.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..84e63f7cc7cf39594e554c7a473538ae15c7b8ad --- /dev/null +++ b/C#.NET/source/YitIdGen.WinFormApp/StartForm.Designer.cs @@ -0,0 +1,90 @@ + +namespace WInFormApp +{ + partial class StartForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.btnGen = new System.Windows.Forms.Button(); + this.txtIdList = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // btnGen + // + this.btnGen.Location = new System.Drawing.Point(12, 385); + this.btnGen.Name = "btnGen"; + this.btnGen.Size = new System.Drawing.Size(170, 64); + this.btnGen.TabIndex = 0; + this.btnGen.Text = "注册"; + this.btnGen.UseVisualStyleBackColor = true; + this.btnGen.Click += new System.EventHandler(this.btnGen_Click); + // + // txtIdList + // + this.txtIdList.Location = new System.Drawing.Point(12, 12); + this.txtIdList.Multiline = true; + this.txtIdList.Name = "txtIdList"; + this.txtIdList.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.txtIdList.Size = new System.Drawing.Size(443, 346); + this.txtIdList.TabIndex = 1; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(286, 385); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(170, 64); + this.button1.TabIndex = 2; + this.button1.Text = "注销"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // StartForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 24F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(468, 514); + this.Controls.Add(this.button1); + this.Controls.Add(this.txtIdList); + this.Controls.Add(this.btnGen); + this.Name = "StartForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "TestForm"; + this.Load += new System.EventHandler(this.Form1_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button btnGen; + private System.Windows.Forms.TextBox txtIdList; + private System.Windows.Forms.Button button1; + } +} + diff --git a/C#.NET/source/YitIdGen.WinFormApp/StartForm.cs b/C#.NET/source/YitIdGen.WinFormApp/StartForm.cs new file mode 100644 index 0000000000000000000000000000000000000000..5bf016b19be23f837f07e8340ac7022ca6892260 --- /dev/null +++ b/C#.NET/source/YitIdGen.WinFormApp/StartForm.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WInFormApp +{ + public partial class StartForm : Form + { + public StartForm() + { + InitializeComponent(); + } + + [DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] + public static extern long NextId(); + + [DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] + public static extern long NextId2(); + + [DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] + public static extern long RegisterWorkerId(string ip, int port, string password, int maxWorkerIdNumber); + //public static extern ulong RegisterWorkerId2(); + + [DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] + public static extern long UnRegisterWorkerId(); + + + [DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] + public static extern void SetWorkerId(uint workerId); + + [DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] + public static extern int Test(); + + [DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] + public static extern int GetWorkerId(string ip, int port); + + + private void Form1_Load(object sender, EventArgs e) + { + + } + + private void btnGen_Click(object sender, EventArgs e) + { + try + { + var ip = "localhost"; + + //txtIdList.Text += RegisterWorkerId(Encoding.UTF8.GetBytes(ip), 6379) + "\r\n"; + txtIdList.Text += RegisterWorkerId(ip, 6379, "", 4) + "\r\n"; + //txtIdList.Text += RegisterWorkerId() + "\r\n"; + + //txtIdList.Text += Test() + "\r\n"; + } + catch (Exception ex) + { + txtIdList.Text = ex.Message; + } + } + + private void button1_Click(object sender, EventArgs e) + { + UnRegisterWorkerId(); + // GetWorkerId("localhost", 6379); + } + } +} diff --git a/C#.NET/source/YitIdGen.WinFormApp/StartForm.resx b/C#.NET/source/YitIdGen.WinFormApp/StartForm.resx new file mode 100644 index 0000000000000000000000000000000000000000..b5ae26c78e0760dae8761d28dcd40bf66208d7aa --- /dev/null +++ b/C#.NET/source/YitIdGen.WinFormApp/StartForm.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/C#.NET/source/YitIdGen.WinFormApp/YitIdGen.WinFormApp.csproj b/C#.NET/source/YitIdGen.WinFormApp/YitIdGen.WinFormApp.csproj new file mode 100644 index 0000000000000000000000000000000000000000..2bbc71613bd11e751534b9d1d36d0a712f415b5a --- /dev/null +++ b/C#.NET/source/YitIdGen.WinFormApp/YitIdGen.WinFormApp.csproj @@ -0,0 +1,19 @@ + + + + WinExe + net5.0-windows + true + + + + + + + + + PreserveNewest + + + + \ No newline at end of file diff --git a/C#.NET/source/YitIdGen.WinFormApp/yitidgen.dll b/C#.NET/source/YitIdGen.WinFormApp/yitidgen.dll new file mode 100644 index 0000000000000000000000000000000000000000..b3b9a924d63a2c36d1701f292b3a46e4c6494820 Binary files /dev/null and b/C#.NET/source/YitIdGen.WinFormApp/yitidgen.dll differ diff --git a/C#.NET/source/Yitter.IdGen.sln b/C#.NET/source/Yitter.IdGen.sln index 2cbc6eac6415d2f8a64d3447fc9d073efd38d57b..2daaa913778cda10ae07e8a1216691cd328d3d80 100644 --- a/C#.NET/source/Yitter.IdGen.sln +++ b/C#.NET/source/Yitter.IdGen.sln @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yitter.IdGenerator", "Yitte EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yitter.IdGenTest", "Yitter.IdGenTest\Yitter.IdGenTest.csproj", "{67426F7D-0A3B-4645-B4D7-5487215D3E2B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YitIdGen.WinFormApp", "YitIdGen.WinFormApp\YitIdGen.WinFormApp.csproj", "{1035D82E-3F37-4940-AA32-5D1E0E53AFA5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +23,10 @@ Global {67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Debug|Any CPU.Build.0 = Debug|Any CPU {67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Release|Any CPU.ActiveCfg = Release|Any CPU {67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Release|Any CPU.Build.0 = Release|Any CPU + {1035D82E-3F37-4940-AA32-5D1E0E53AFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1035D82E-3F37-4940-AA32-5D1E0E53AFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1035D82E-3F37-4940-AA32-5D1E0E53AFA5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1035D82E-3F37-4940-AA32-5D1E0E53AFA5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/C#.NET/source/Yitter.IdGenTest/GenTest.cs b/C#.NET/source/Yitter.IdGenTest/GenTest.cs index b5383c42f7b01d97f859f895284085305919c006..5ebf05e9ad7acb25f0890a0ffd950de28f4ff8ba 100644 --- a/C#.NET/source/Yitter.IdGenTest/GenTest.cs +++ b/C#.NET/source/Yitter.IdGenTest/GenTest.cs @@ -15,7 +15,6 @@ namespace Yitter.OrgSystem.TestA public IList idList = new List(); private int GenIdCount; private int WorkerId; - public GenTest(IIdGenerator idGen, int genIdCount, int workerId) { diff --git a/C#.NET/source/Yitter.IdGenTest/Program.cs b/C#.NET/source/Yitter.IdGenTest/Program.cs index 3f57391c1e15e3cbdaf2bb7fb9c66faad7798329..42e9d699f604d8bebc43f3907eb367a60106c660 100644 --- a/C#.NET/source/Yitter.IdGenTest/Program.cs +++ b/C#.NET/source/Yitter.IdGenTest/Program.cs @@ -55,9 +55,9 @@ namespace Yitter.OrgSystem.TestA while (true) { - //RunSingle(); + RunSingle(); + //CallDll(); //Go(options); - CallDll(); Thread.Sleep(1000); // 每隔1秒执行一次Go } } @@ -65,13 +65,13 @@ namespace Yitter.OrgSystem.TestA //[DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] //public static extern long NextId(); - [DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] + [DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] public static extern long NextId(); - [DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] + [DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] public static extern void SetWorkerId(uint workerId); - [DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] + [DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] public static extern int TestId(); private static void CallDll() diff --git a/Go/source/gen/YitIdHelper.go b/Go/source/gen/YitIdHelper.go deleted file mode 100644 index fc93df8a7119dac6368cc1e54f9fe0c29433cf4f..0000000000000000000000000000000000000000 --- a/Go/source/gen/YitIdHelper.go +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 版权属于:yitter(yitter@126.com) - * 代码编辑:guoyahao - * 代码修订:yitter - * 开源地址:https://gitee.com/yitter/idgenerator - */ -package gen - -import ( - "sync" - "yitidgen/contract" -) - -var ins *YitIdHelper -var once sync.Once - -type YitIdHelper struct { - idGenInstance interface { - NewLong() uint64 - } -} - -func GetIns() *YitIdHelper { - once.Do(func() { - ins = &YitIdHelper{} - }) - return ins -} - -func (yih *YitIdHelper) GetIdGenInstance() interface{} { - return yih.idGenInstance -} - -func (yih *YitIdHelper) SetIdGenerator(options *contract.IdGeneratorOptions) { - yih.idGenInstance = NewDefaultIdGenerator(options) -} - -func (yih *YitIdHelper) NextId() uint64 { - once.Do(func() { - if yih.idGenInstance == nil { - options := contract.NewIdGeneratorOptions(1) - yih.idGenInstance = NewDefaultIdGenerator(options) - } - }) - - return yih.idGenInstance.NewLong() -} diff --git a/Go/source/go.mod b/Go/source/go.mod index 8eafd7d48c7c18fd42f7859adfa5c28e8dd2db45..c1c9b3c9e3216ca6c5a58f385c2658713c34a77a 100644 --- a/Go/source/go.mod +++ b/Go/source/go.mod @@ -1 +1,9 @@ -module "yitidgen" \ No newline at end of file +module yitidgen + +go 1.16 + +require ( + github.com/go-redis/redis v6.15.9+incompatible + github.com/onsi/ginkgo v1.15.2 // indirect + github.com/onsi/gomega v1.11.0 // indirect +) diff --git a/Go/source/go.sum b/Go/source/go.sum new file mode 100644 index 0000000000000000000000000000000000000000..b98c3ea9190227aeb76860bd1646919df65f6656 --- /dev/null +++ b/Go/source/go.sum @@ -0,0 +1,82 @@ +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= +github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= +github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/Go/source/gen/DefaultIdGenerator.go b/Go/source/idgen/DefaultIdGenerator.go similarity index 99% rename from Go/source/gen/DefaultIdGenerator.go rename to Go/source/idgen/DefaultIdGenerator.go index 8d891380597ab7af060b79090b740d8d8f50257f..5176980854d9d0c9197ce7e3b3cab03ee217f88b 100644 --- a/Go/source/gen/DefaultIdGenerator.go +++ b/Go/source/idgen/DefaultIdGenerator.go @@ -4,7 +4,7 @@ * 代码修订:yitter * 开源地址:https://gitee.com/yitter/idgenerator */ -package gen +package idgen import ( "time" diff --git a/Go/source/idgen/YitIdHelper.go b/Go/source/idgen/YitIdHelper.go new file mode 100644 index 0000000000000000000000000000000000000000..a7540c9dd49328bce7fccfbeb8d1c857d65f7b2a --- /dev/null +++ b/Go/source/idgen/YitIdHelper.go @@ -0,0 +1,68 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码编辑:guoyahao + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package idgen + +import ( + "sync" + "yitidgen/contract" +) + +//var yitIdHelper *YitIdHelper +//var once sync.Once + +var idGenerator *DefaultIdGenerator +var singletonMutex sync.Mutex + +type YitIdHelper struct { + idGenInstance interface { + NewLong() uint64 + } +} + +// +//func GetIns() *YitIdHelper { +// once.Do(func() { +// yitIdHelper = &YitIdHelper{} +// }) +// return yitIdHelper +//} +// +//func (yih *YitIdHelper) GetIdGenInstance() interface{} { +// return yih.idGenInstance +//} +// +//func (yih *YitIdHelper) SetIdGenerator(options *contract.IdGeneratorOptions) { +// yih.idGenInstance = NewDefaultIdGenerator(options) +//} +// +//func (yih *YitIdHelper) NextId() uint64 { +// once.Do(func() { +// if yih.idGenInstance == nil { +// options := contract.NewIdGeneratorOptions(1) +// yih.idGenInstance = NewDefaultIdGenerator(options) +// } +// }) +// +// return yih.idGenInstance.NewLong() +//} + +func SetIdGenerator(options *contract.IdGeneratorOptions) { + singletonMutex.Lock() + idGenerator = NewDefaultIdGenerator(options) + singletonMutex.Unlock() +} + +func NextId() uint64 { + if idGenerator == nil { + singletonMutex.Lock() + options := contract.NewIdGeneratorOptions(1) + idGenerator = NewDefaultIdGenerator(options) + singletonMutex.Unlock() + } + + return idGenerator.NewLong() +} diff --git a/Go/source/main.go b/Go/source/main.go new file mode 100644 index 0000000000000000000000000000000000000000..4eb085f4bc502c731a66093c1c7e871d560a43ca --- /dev/null +++ b/Go/source/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "C" + "fmt" + "time" + "yitidgen/contract" + "yitidgen/idgen" + "yitidgen/regworkerid" +) + +//export SetOptions +func SetOptions(workerId uint16) { + var options = contract.NewIdGeneratorOptions(workerId) + idgen.SetIdGenerator(options) +} + +//export NextId +func NextId() uint64 { + return idgen.NextId() +} + +//export RegisterWorkerId +func RegisterWorkerId(ip *C.char, port int, password *C.char, maxWorkerId int) int { + return regworkerid.RegisterWorkerId(C.GoString(ip), port, C.GoString(password), maxWorkerId) +} + +//export UnRegisterWorkerId +func UnRegisterWorkerId() { + regworkerid.UnRegisterWorkerId() +} + +func main() { + // 方法一:直接采用默认方法生成一个Id + fmt.Println("生成的Id:", idgen.NextId()) + + fmt.Println("生成的Id:", regworkerid.RegisterWorkerId("localhost", 6379, "", 4)) + + return + // 方法二:自定义参数 + var options = contract.NewIdGeneratorOptions(1) + options.WorkerIdBitLength = 6 + options.SeqBitLength = 6 + options.TopOverCostCount = 2000 + options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 + idgen.SetIdGenerator(options) + + var genCount = 50000 + + for { + var begin = time.Now().UnixNano() / 1e6 + for i := 0; i < genCount; i++ { + idgen.NextId() + } + var end = time.Now().UnixNano() / 1e6 + + fmt.Println(end - begin) + time.Sleep(time.Duration(1000) * time.Millisecond) + } + +} + +// go build -o target\yitidgengo.dll -buildmode=c-shared main.go + +//var yid = idgen.YitIdHelper{} +//yid.SetIdGenerator(options) +//fmt.Println(yid.NextId()) diff --git a/Go/source/regworkerid/reghelper.go b/Go/source/regworkerid/reghelper.go new file mode 100644 index 0000000000000000000000000000000000000000..642aca6f50cf07da212556c3ff7008451fd6a7d5 --- /dev/null +++ b/Go/source/regworkerid/reghelper.go @@ -0,0 +1,230 @@ +package regworkerid + +import ( + "fmt" + "github.com/go-redis/redis" + "strconv" + "sync" + "time" +) + +var Client *redis.Client + +var _usingWorkerId int = -1 +var _maxWorkerId int = 0 +var _loopCount int = 0 +var _liftIndex int = -1 +var _workerIdLock sync.Mutex + +const CurrentWidIndexKey string = "IdGen:WorkerId:Index" +const WidKeyPrefix string = "IdGen:WorkerId:Value:" +const WorkerIdFlag = "Y" // WorkerId 存储标记 +const WorkerIdLifeTimeSeconds = 15 // WorkerIdFlag 有效期(单位秒,最好是3的倍数) +const Log = false + +func UnRegisterWorkerId() { + if _usingWorkerId < 0 { + return + } + _workerIdLock.Lock() + Client.Del(WidKeyPrefix + strconv.Itoa(_usingWorkerId)) + _usingWorkerId = -1 + _liftIndex = -1 + _workerIdLock.Unlock() +} + +func RegisterWorkerId(ip string, port int, password string, maxWorkerId int) int { + // maxWorkerId不能小于0 + if maxWorkerId < 0 { + return -1 + } + + // 如果当前已注册过 WorkerId,则先注销,并终止先前的自动续期线程 + if _usingWorkerId > -1 { + UnRegisterWorkerId() + } + + _maxWorkerId = maxWorkerId + Client = redis.NewClient(&redis.Options{ + Addr: string(ip) + ":" + strconv.Itoa(port), + PoolSize: 1000, + ReadTimeout: time.Millisecond * time.Duration(100), + WriteTimeout: time.Millisecond * time.Duration(100), + IdleTimeout: time.Second * time.Duration(60), + Password: password, + }) + _, err := Client.Ping().Result() + if err != nil { + panic("init redis error") + } else { + if Log { + fmt.Println("init redis ok") + } + } + + _loopCount = 0 + return getNextWorkerId() +} + +func getNextWorkerId() int { + // 获取当前 WorkerIdIndex + // var currentId = int(Client.Incr(CurrentWidIndexKey).Val()) + r, err := Client.Incr(CurrentWidIndexKey).Result() + if err != nil { + return 0 + } + + currentId := int(r) + if Log { + fmt.Println("Begin currentId:" + strconv.Itoa(currentId)) + } + + // 如果 Index 大于最大值,则重置 + if currentId > _maxWorkerId { + if canReset() { + // 当前应用获得重置 WorkerIdIndex 的权限 + setWorkerIdIndex(-1) + endReset() // 此步有可能不被执行? + _loopCount++ + // 超过一定次数,直接终止操作 + if _loopCount > 10 { + return -1 + } + + // if _loopCount > 2 { + // 如果超过2个循环,则暂停1s + time.Sleep(time.Duration(500*_loopCount) * time.Millisecond) + //_loopCount = 0 + //} + + if Log { + fmt.Println("canReset loop") + } + + return getNextWorkerId() + } else { + // 如果有其它应用正在编辑,则本应用暂停1s后,再继续 + time.Sleep(time.Duration(1000) * time.Millisecond) + + if Log { + fmt.Println("not canReset loop") + } + + return getNextWorkerId() + } + } + + if Log { + fmt.Println("currentId:" + strconv.Itoa(currentId)) + } + + if isAvailable(currentId) { + if Log { + fmt.Println("AA: isAvailable:" + strconv.Itoa(currentId)) + } + + // 最新获得的 WorkerIdIndex,在 redis 中是可用状态 + setWorkerIdFlag(currentId) + _usingWorkerId = currentId + + // 获取到可用 WorkerId 后,启用新线程,每隔 1/3个 WorkerIdLifeTimeSeconds 时间,向服务器续期(延长一次 LifeTime) + _liftIndex++ + go extendWorkerIdLifeTime(_liftIndex) + + return currentId + } else { + if Log { + fmt.Println("BB: not isAvailable:" + strconv.Itoa(currentId)) + } + // 最新获得的 WorkerIdIndex,在 redis 中是不可用状态,则继续下一个 WorkerIdIndex + return getNextWorkerId() + } +} + +func extendWorkerIdLifeTime(lifeIndex int) { + var index = lifeIndex + for { + time.Sleep(time.Duration(WorkerIdLifeTimeSeconds/3) * time.Millisecond) + + _workerIdLock.Lock() + if index != _liftIndex { + // 如果临时变量 index 不等于 全局变量 _liftIndex,表明全局状态被修改,当前线程可终止 + break + } + + // 已经被注销,则终止(此步是上一步的二次验证) + if _usingWorkerId < 0 { + break + } + + extendWorkerIdFlag(_usingWorkerId) + _workerIdLock.Unlock() + } +} + +func get(key string) (string, bool) { + r, err := Client.Get(key).Result() + if err != nil { + return "", false + } + return r, true +} + +func set(key string, val string, expTime int32) { + Client.Set(key, val, time.Duration(expTime)*time.Second) +} + +func setWorkerIdIndex(val int) { + Client.Set(CurrentWidIndexKey, val, 0) +} + +func setWorkerIdFlag(index int) { + Client.Set(WidKeyPrefix+strconv.Itoa(index), WorkerIdFlag, time.Duration(WorkerIdLifeTimeSeconds)*time.Second) +} + +func extendWorkerIdFlag(index int) { + Client.Expire(WidKeyPrefix+strconv.Itoa(index), time.Duration(WorkerIdLifeTimeSeconds)*time.Second) +} + +func canReset() bool { + r, err := Client.Incr(WidKeyPrefix + "Edit").Result() + if err != nil { + return false + } + + if Log { + fmt.Println("canReset:" + string(r)) + } + + return r != 1 +} + +func endReset() { + // Client.Set(WidKeyPrefix+"Edit", 0, time.Duration(2)*time.Second) + Client.Set(WidKeyPrefix+"Edit", 0, 0) +} + +func getWorkerIdFlag(index int) (string, bool) { + r, err := Client.Get(WidKeyPrefix + strconv.Itoa(index)).Result() + if err != nil { + return "", false + } + return r, true +} + +func isAvailable(index int) bool { + r, err := Client.Get(WidKeyPrefix + strconv.Itoa(index)).Result() + + if Log { + fmt.Println("XX isAvailable:" + r) + fmt.Println("YY isAvailable:" + err.Error()) + } + + if err != nil { + if err.Error() == "redis: nil" { + return true + } + return false + } + return r != WorkerIdFlag +} diff --git a/Go/source/target/go_build_main_go.exe b/Go/source/target/go_build_main_go.exe new file mode 100644 index 0000000000000000000000000000000000000000..76cc0b747e264977eda8b4d4c779234dc85964a4 Binary files /dev/null and b/Go/source/target/go_build_main_go.exe differ diff --git a/Go/source/target/main.dll b/Go/source/target/main.dll new file mode 100644 index 0000000000000000000000000000000000000000..bc7f4b2328db12bad946ad3200c1eb5fe2a579b6 Binary files /dev/null and b/Go/source/target/main.dll differ diff --git a/Go/source/target/main.h b/Go/source/target/main.h new file mode 100644 index 0000000000000000000000000000000000000000..8eb543cf60e6d40f38fd91ea181a67652c7073e7 --- /dev/null +++ b/Go/source/target/main.h @@ -0,0 +1,75 @@ +/* Code generated by cmd/cgo; DO NOT EDIT. */ + +/* package command-line-arguments */ + + +#line 1 "cgo-builtin-export-prolog" + +#include /* for ptrdiff_t below */ + +#ifndef GO_CGO_EXPORT_PROLOGUE_H +#define GO_CGO_EXPORT_PROLOGUE_H + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef struct { const char *p; ptrdiff_t n; } _GoString_; +#endif + +#endif + +/* Start of preamble from import "C" comments. */ + + + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef _GoString_ GoString; +#endif +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern __declspec(dllexport) GoUint64 NextId(); + +#ifdef __cplusplus +} +#endif diff --git a/Go/source/target/yitidgen.dll b/Go/source/target/yitidgen.dll new file mode 100644 index 0000000000000000000000000000000000000000..2f42ebe005a673fe15cb9046e0db2c4436168ee8 Binary files /dev/null and b/Go/source/target/yitidgen.dll differ diff --git a/Go/source/target/yitidgen.h b/Go/source/target/yitidgen.h new file mode 100644 index 0000000000000000000000000000000000000000..8eb543cf60e6d40f38fd91ea181a67652c7073e7 --- /dev/null +++ b/Go/source/target/yitidgen.h @@ -0,0 +1,75 @@ +/* Code generated by cmd/cgo; DO NOT EDIT. */ + +/* package command-line-arguments */ + + +#line 1 "cgo-builtin-export-prolog" + +#include /* for ptrdiff_t below */ + +#ifndef GO_CGO_EXPORT_PROLOGUE_H +#define GO_CGO_EXPORT_PROLOGUE_H + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef struct { const char *p; ptrdiff_t n; } _GoString_; +#endif + +#endif + +/* Start of preamble from import "C" comments. */ + + + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef _GoString_ GoString; +#endif +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern __declspec(dllexport) GoUint64 NextId(); + +#ifdef __cplusplus +} +#endif diff --git a/Go/source/target/yitidgengo.dll b/Go/source/target/yitidgengo.dll new file mode 100644 index 0000000000000000000000000000000000000000..87c7cd63ba9b20bae9b918c4e72142e661fdc0a1 Binary files /dev/null and b/Go/source/target/yitidgengo.dll differ diff --git a/Go/source/target/yitidgengo.h b/Go/source/target/yitidgengo.h new file mode 100644 index 0000000000000000000000000000000000000000..1b2f837656d48a565233e6173798f6d357304f3d --- /dev/null +++ b/Go/source/target/yitidgengo.h @@ -0,0 +1,78 @@ +/* Code generated by cmd/cgo; DO NOT EDIT. */ + +/* package command-line-arguments */ + + +#line 1 "cgo-builtin-export-prolog" + +#include /* for ptrdiff_t below */ + +#ifndef GO_CGO_EXPORT_PROLOGUE_H +#define GO_CGO_EXPORT_PROLOGUE_H + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef struct { const char *p; ptrdiff_t n; } _GoString_; +#endif + +#endif + +/* Start of preamble from import "C" comments. */ + + + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef _GoString_ GoString; +#endif +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern __declspec(dllexport) void SetOptions(GoUint16 workerId); +extern __declspec(dllexport) GoUint64 NextId(); +extern __declspec(dllexport) GoInt RegisterWorkerId(char* ip, GoInt port, char* password, GoInt maxWorkerId); +extern __declspec(dllexport) void UnRegisterWorkerId(); + +#ifdef __cplusplus +} +#endif diff --git a/Go/source/test/main.go b/Go/source/test/main.go deleted file mode 100644 index f1263c58173a956c43a2ca08e7af27807dfa42e0..0000000000000000000000000000000000000000 --- a/Go/source/test/main.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "C" - "fmt" - "time" - "yitidgen/contract" - "yitidgen/gen" -) - - -//export NextId -func NextId() uint64{ - return gen.GetIns().NextId() -} - -func main() { - // 方法一:直接采用默认方法生成一个Id - var yid = gen.YitIdHelper{} - fmt.Println(yid.NextId()) - - // 方法二:自定义参数 - var options = contract.NewIdGeneratorOptions(1) - //options.WorkerIdBitLength = 6 - //options.SeqBitLength = 6 - //options.TopOverCostCount = 2000 - //options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 - yid.SetIdGenerator(options) - - var times = 50000 - - for { - var begin = time.Now().UnixNano() / 1e6 - for i := 0; i < times; i++ { - yid.NextId() - } - var end = time.Now().UnixNano() / 1e6 - - fmt.Println(end - begin) - time.Sleep(time.Duration(1000) * time.Millisecond) - } - -} diff --git a/PHP/README.md b/PHP/README.md deleted file mode 100644 index aab2eefd5982fb7db694dd8e89128adb32d0c504..0000000000000000000000000000000000000000 --- a/PHP/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# idgenerator - -something is going on. - diff --git a/README.md b/README.md index 6ff69a5e604a9f9560c6d3fe599ce7fb5c14f5de..6acb34b7b07894655a70cfe65e88c1e042fc4190 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# IdGenerator SnowFlake 雪花算法 原生多语言版本 顶尖优化 超强效能 +# 唯一ID生成器 IdGenerator SnowFlake 雪花算法 原生多语言源码 ## 介绍 @@ -8,6 +8,8 @@ 3.原生支持 C#/Java/Go/Rust/C 等语言,并由 Rust 提供 PHP、Python、Node.js、Ruby 等语言多线程安全调用库(FFI)。 +4.支持单服务部署、多服务部署、容器自动化服务 + ## 技术支持 @@ -27,13 +29,13 @@ QQ群:646049993 4.如果这样的主键值太长,超过前端 JS Number 类型最大值,须把 Long 型转换为 String 型,你会觉得有点沮丧。 -5.哪怕 Guid 能自增,但占用空间大,索引速度慢,所以你也不想用它。 +5.尽管 Guid 能自增,但占用空间大,索引速度慢,你也不想用它。 -6.你的应用实例可能超过50个,每个并发请求可达10W/s。 +6.应用实例可能超过50个,每个并发请求可达10W/s。 7.在容器环境部署应用(水平扩展、自动伸缩)。 -8.你可不想 Id 生成器依赖 redis 的自增操作。 +8.不想依赖 redis 的自增操作。 9.你希望系统运行 100 年以上。 @@ -164,7 +166,15 @@ ID示例(基于默认配置): 7.不要修改核心算法。本算法内部参数较多,逻辑较为复杂,在你尚未掌握核心逻辑时,请勿尝试修改核心代码且用于生产环境,除非通过大量细致、科学的测试验证。 -#### 大型分布式集成 +#### 自动/手动 设置 WorkerId + +1.如果Id生成服务是明确的,可在初始化时,手动设置 WorkerId。 + +2.如果Id生成服务是不明确的,如容器环境:动态的、自动执行、生命周期完全自动化,可在初始化时通过Redis,自动申请 WorkerId,详见“Tools/AutoRegisterWorkerId” + + + +#### 其它分布式集成 1.可增加 WorkerIdBitLength 到最大20,支持 1,048,576 个节点,且不影响上述并发性能。[算法支持] diff --git a/Rust/source/Cargo.lock b/Rust/source/Cargo.lock index 6a8c0af06fc40455c843ae566e52ca2feb76a55e..33c508a9d8a7115323b0d48be8cc95f9f2355a5f 100644 --- a/Rust/source/Cargo.lock +++ b/Rust/source/Cargo.lock @@ -1,11 +1,28 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "async-trait" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "bytes" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" + [[package]] name = "chrono" version = "0.4.19" @@ -19,6 +36,49 @@ dependencies = [ "winapi", ] +[[package]] +name = "combine" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4369b5e4c0cddf64ad8981c0111e7df4f7078f4d6ba98fb31f2e17c4c57b7e" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "idna" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + [[package]] name = "lazy_static" version = "1.4.0" @@ -31,6 +91,18 @@ version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae" +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + [[package]] name = "num-integer" version = "0.1.44" @@ -50,6 +122,62 @@ dependencies = [ "autocfg", ] +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redis" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeb8f8d059ead7805e171fc22de8348a3d611c0f985aaa4f5cf6c0dfc7645407" +dependencies = [ + "async-trait", + "combine", + "dtoa", + "itoa", + "percent-encoding", + "sha1", + "url", +] + +[[package]] +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" + +[[package]] +name = "syn" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "time" version = "0.1.44" @@ -61,6 +189,57 @@ dependencies = [ "winapi", ] +[[package]] +name = "tinyvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "url" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -95,4 +274,6 @@ version = "1.0.0" dependencies = [ "chrono", "lazy_static", + "libc", + "redis", ] diff --git a/Rust/source/Cargo.toml b/Rust/source/Cargo.toml index 8664c2f47b50b6679e279a4193d4633cb5dcbcbe..64350e14a7093cec581d2ec61c5c7c976927246a 100644 --- a/Rust/source/Cargo.toml +++ b/Rust/source/Cargo.toml @@ -9,6 +9,15 @@ edition = "2018" [dependencies] chrono = "0.4.10" lazy_static = "1.4.0" +#simple_redis = "*" +redis = "0.20.0" +libc="*" + +#actix = "0.9.0" +#actix-web = "2.0" +#actix-rt = "1.0" +#actix-redis = "0.8.0" +#redis-async = "0.6.1" [lib] name = "yitidgen" diff --git a/Rust/source/src/lib.rs b/Rust/source/src/lib.rs index 080215e965dcb5119faa62a61066798f7440edd4..b1e797b97023c242f360d921a96d8132fef075cb 100644 --- a/Rust/source/src/lib.rs +++ b/Rust/source/src/lib.rs @@ -3,6 +3,23 @@ mod yitgen; use yitgen::gen::YitIdHelper; use yitgen::contract::*; +#[macro_use] +extern crate lazy_static; +extern crate redis; +extern crate libc; + +use redis::Commands; + +use libc::{c_char, uint32_t}; +use std::ffi::{CStr, CString}; +use std::str; + +lazy_static! { + //static ref TestValue: Vec = vec!(0); + // static ref MAP: HashMap = HashMap::new(); + } + + // #[export_name = "SetIdGenerator"] #[no_mangle] pub extern "C" fn SetIdGenerator(options: IdGeneratorOptions) { @@ -19,3 +36,64 @@ pub extern "C" fn NextId() -> i64 { YitIdHelper::NextId() } +static mut TestValue: i32 = 0; + +#[no_mangle] +pub extern "C" fn Test() -> i32 { + unsafe { + TestValue += 1; + return TestValue; + } +} + +#[no_mangle] +pub extern "C" fn GetWorkerId(ip: *const c_char, port: i32) -> redis::RedisResult { + // let c_str = unsafe { + // assert!(!ip.is_null()); + // CStr::from_ptr(ip) + // }; + // + // let r_str = c_str.to_str(); + + // connect to redis + // let client = redis::Client::open(format!("redis://{}:{}/", String::from(r_str).to_string(), port))?; + let client = redis::Client::open(format!("redis://localhost:{}/", port))?; + + let mut con = client.get_connection()?; + // throw away the result, just make sure it does not fail + unsafe { + let _: () = con.set("my_key111", TestValue.clone())?; + } + con.get("my_key") +// read back the key and return it. Because the return value +// from the function is a result for integer this will automatically +// convert into one. +// + +// match simple_redis::create(&format!("redis://{}:{}/", ip, port)) { +// Ok(mut client) => { +// println!("Created Redis Client"); +// +// let valueString = TestValue.to_string(); +// let valueString2 = (*TestValue).to_string(); +// +// match client.set("my_key", valueString) { +// Err(error) => println!("Unable to set value in Redis: {}", error), +// _ => println!("Value set in Redis") +// }; +// +// match client.set("my_key2", valueString2) { +// Err(error) => println!("Unable to set value in Redis: {}", error), +// _ => println!("Value set in Redis") +// }; +// +// match client.quit() { +// Err(error) => println!("Error: {}", error), +// _ => println!("Connection Closed.") +// } +// } +// Err(error) => println!("Unable to create Redis client: {}", error) +// } + +//return 1; +} \ No newline at end of file diff --git a/Rust/source/src/main.rs b/Rust/source/src/main.rs index 88ab0ff56d6c97cd712fa49a0e6ef276f027870e..9870a12864d98eeb4bf474c023051bccf8c77cf5 100644 --- a/Rust/source/src/main.rs +++ b/Rust/source/src/main.rs @@ -6,6 +6,7 @@ use std::thread; use chrono::Utc; use std::time::Duration; + fn main() { println!("Hello, world! Rust"); @@ -22,6 +23,8 @@ fn main() { //... 可以继续设置其它 options 参数 YitIdHelper::SetIdGenerator(options); + set_redis(); + // 以下开始测试生成数据,默认5W,单线程,可以修改 multiThread=true 启用多线程。 loop { let mut i = 0; @@ -51,3 +54,24 @@ fn main() { } } +fn set_redis() { + + // match simple_redis::create("redis://127.0.0.1:6379/") { + // Ok(mut client) => { + // println!("Created Redis Client"); + // + // match client.set("my_key", "my_value") { + // Err(error) => println!("Unable to set value in Redis: {}", error), + // _ => println!("Value set in Redis") + // }; + // + // match client.quit() { + // Err(error) => println!("Error: {}", error), + // _ => println!("Connection Closed.") + // } + // }, + // Err(error) => println!("Unable to create Redis client: {}", error) + // } + + } + diff --git a/Rust/source/src/yitgen/core/snow_worker_m1.rs b/Rust/source/src/yitgen/core/snow_worker_m1.rs index 7ed297ea5cbfb2dc770acbc2e7fc3b8c9c345150..742a7e94d0cdefe0387da9b98ff700b4bf5649ef 100644 --- a/Rust/source/src/yitgen/core/snow_worker_m1.rs +++ b/Rust/source/src/yitgen/core/snow_worker_m1.rs @@ -6,7 +6,7 @@ use super::super::contract::*; use std::{thread}; use chrono::Utc; use std::thread::sleep; -use lazy_static::lazy_static; +// use lazy_static::lazy_static; pub struct SnowWorkerM1 { ///基础时间 diff --git a/Rust/source/src/yitgen/gen/default_id_generator.rs b/Rust/source/src/yitgen/gen/default_id_generator.rs index c566b5a9818933bd9012eca5b54fd17dc3e607ca..50fa71bc4d2e88400492c31a6fd6f2f1007fde18 100644 --- a/Rust/source/src/yitgen/gen/default_id_generator.rs +++ b/Rust/source/src/yitgen/gen/default_id_generator.rs @@ -12,7 +12,7 @@ use std::sync::Mutex; use std::sync::Arc; use std::borrow::BorrowMut; -static mut instance2: Option>> = None; +// static mut instance2: Option>> = None; pub struct DefaultIdGenerator { pub Worker: SnowWorkerM1, diff --git a/Tools/AutoRegisterWorkerId/README.md b/Tools/AutoRegisterWorkerId/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8e57b143c650c79fbd846d790b74e88c0fc5d5ea --- /dev/null +++ b/Tools/AutoRegisterWorkerId/README.md @@ -0,0 +1,16 @@ +# idgenerator + +## AutoRegisterWorkerId + +Զע WorkerId Ĺߡ¼ʹá + + +## 輯 + +ȫִһΣ + +1.Redisӡ + +2.ȡ WorkerIdֵ IdGenerator + + diff --git a/Tools/FFI for Python-Node-PHP/README.md b/Tools/FFI for Python-Node-PHP/README.md new file mode 100644 index 0000000000000000000000000000000000000000..24ab2f6eb2582af0ebb398d4d1ed529837c06d5d --- /dev/null +++ b/Tools/FFI for Python-Node-PHP/README.md @@ -0,0 +1,7 @@ +# idgenerator + +## FFI + +Pytonnode.jsPHP ȿͨ FFI ʽö̬ ID + +ォṩͬϵͳĶ̬ \ No newline at end of file diff --git a/ZeOthers/README.md b/Tools/OtherLanguages/README.md similarity index 100% rename from ZeOthers/README.md rename to Tools/OtherLanguages/README.md diff --git a/ZeOthers/Vlang/README.md b/Tools/OtherLanguages/Vlang/README.md similarity index 100% rename from ZeOthers/Vlang/README.md rename to Tools/OtherLanguages/Vlang/README.md diff --git a/ZeOthers/Vlang/source/contract/IIdGenerator.v b/Tools/OtherLanguages/Vlang/source/contract/IIdGenerator.v similarity index 100% rename from ZeOthers/Vlang/source/contract/IIdGenerator.v rename to Tools/OtherLanguages/Vlang/source/contract/IIdGenerator.v diff --git a/ZeOthers/Vlang/source/contract/ISnowWorker.v b/Tools/OtherLanguages/Vlang/source/contract/ISnowWorker.v similarity index 100% rename from ZeOthers/Vlang/source/contract/ISnowWorker.v rename to Tools/OtherLanguages/Vlang/source/contract/ISnowWorker.v diff --git a/ZeOthers/Vlang/source/contract/IdGeneratorOptions.v b/Tools/OtherLanguages/Vlang/source/contract/IdGeneratorOptions.v similarity index 100% rename from ZeOthers/Vlang/source/contract/IdGeneratorOptions.v rename to Tools/OtherLanguages/Vlang/source/contract/IdGeneratorOptions.v diff --git a/ZeOthers/Vlang/source/core/SnowWorkerM1.v b/Tools/OtherLanguages/Vlang/source/core/SnowWorkerM1.v similarity index 100% rename from ZeOthers/Vlang/source/core/SnowWorkerM1.v rename to Tools/OtherLanguages/Vlang/source/core/SnowWorkerM1.v diff --git a/ZeOthers/Vlang/source/core/SnowWorkerM2.v b/Tools/OtherLanguages/Vlang/source/core/SnowWorkerM2.v similarity index 100% rename from ZeOthers/Vlang/source/core/SnowWorkerM2.v rename to Tools/OtherLanguages/Vlang/source/core/SnowWorkerM2.v diff --git a/ZeOthers/Vlang/source/gen/DefaultIdGenerator.v b/Tools/OtherLanguages/Vlang/source/gen/DefaultIdGenerator.v similarity index 100% rename from ZeOthers/Vlang/source/gen/DefaultIdGenerator.v rename to Tools/OtherLanguages/Vlang/source/gen/DefaultIdGenerator.v diff --git a/ZeOthers/Vlang/source/gen/YitIdHelper.v b/Tools/OtherLanguages/Vlang/source/gen/YitIdHelper.v similarity index 100% rename from ZeOthers/Vlang/source/gen/YitIdHelper.v rename to Tools/OtherLanguages/Vlang/source/gen/YitIdHelper.v diff --git a/ZeOthers/Vlang/source/test b/Tools/OtherLanguages/Vlang/source/test similarity index 100% rename from ZeOthers/Vlang/source/test rename to Tools/OtherLanguages/Vlang/source/test diff --git a/ZeOthers/Vlang/source/test.v b/Tools/OtherLanguages/Vlang/source/test.v similarity index 100% rename from ZeOthers/Vlang/source/test.v rename to Tools/OtherLanguages/Vlang/source/test.v diff --git a/tester/csharp_call_rust.png b/Tools/Testing Data/csharp_call_rust.png similarity index 100% rename from tester/csharp_call_rust.png rename to Tools/Testing Data/csharp_call_rust.png diff --git "a/tester/\346\257\217\346\254\2415W\345\271\266\345\217\221(\345\276\252\347\216\257).png" "b/Tools/Testing Data/\346\257\217\346\254\2415W\345\271\266\345\217\221(\345\276\252\347\216\257).png" similarity index 100% rename from "tester/\346\257\217\346\254\2415W\345\271\266\345\217\221(\345\276\252\347\216\257).png" rename to "Tools/Testing Data/\346\257\217\346\254\2415W\345\271\266\345\217\221(\345\276\252\347\216\257).png" diff --git "a/tester/\347\273\274\345\220\210\346\265\213\350\257\225.png" "b/Tools/Testing Data/\347\273\274\345\220\210\346\265\213\350\257\225.png" similarity index 100% rename from "tester/\347\273\274\345\220\210\346\265\213\350\257\225.png" rename to "Tools/Testing Data/\347\273\274\345\220\210\346\265\213\350\257\225.png"